03a5ec9735153c5d3486eecf6d1a374b655274da
[mesa.git] / src / mesa / swrast / s_depth.c
1 /* $Id: s_depth.c,v 1.15 2002/02/02 21:40:33 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.1
6 *
7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
25 */
26
27
28 #include "glheader.h"
29 #include "context.h"
30 #include "macros.h"
31 #include "mem.h"
32
33 #include "s_depth.h"
34 #include "s_context.h"
35
36
37
38
39 /*
40 * Return address of depth buffer value for given window coord.
41 */
42 GLvoid *
43 _mesa_zbuffer_address(GLcontext *ctx, GLint x, GLint y)
44 {
45 if (ctx->Visual.depthBits <= 16)
46 return (GLushort *) ctx->DrawBuffer->DepthBuffer
47 + ctx->DrawBuffer->Width * y + x;
48 else
49 return (GLuint *) ctx->DrawBuffer->DepthBuffer
50 + ctx->DrawBuffer->Width * y + x;
51 }
52
53
54 #define Z_ADDRESS16( CTX, X, Y ) \
55 ( ((GLushort *) (CTX)->DrawBuffer->DepthBuffer) \
56 + (CTX)->DrawBuffer->Width * (Y) + (X) )
57
58 #define Z_ADDRESS32( CTX, X, Y ) \
59 ( ((GLuint *) (CTX)->DrawBuffer->DepthBuffer) \
60 + (CTX)->DrawBuffer->Width * (Y) + (X) )
61
62
63
64 /**********************************************************************/
65 /***** Depth Testing Functions *****/
66 /**********************************************************************/
67
68
69 /*
70 * Do depth test for an array of fragments. This is used both for
71 * software and hardware Z buffers.
72 * Input: zbuffer - array of z values in the zbuffer
73 * z - array of fragment z values
74 * Return: number of fragments which pass the test.
75 */
76 static GLuint
77 depth_test_span16( GLcontext *ctx, GLuint n,
78 GLushort zbuffer[], const GLdepth z[], GLubyte mask[] )
79 {
80 GLuint passed = 0;
81
82 /* switch cases ordered from most frequent to less frequent */
83 switch (ctx->Depth.Func) {
84 case GL_LESS:
85 if (ctx->Depth.Mask) {
86 /* Update Z buffer */
87 GLuint i;
88 for (i=0; i<n; i++) {
89 if (mask[i]) {
90 if (z[i] < zbuffer[i]) {
91 /* pass */
92 zbuffer[i] = z[i];
93 passed++;
94 }
95 else {
96 /* fail */
97 mask[i] = 0;
98 }
99 }
100 }
101 }
102 else {
103 /* Don't update Z buffer */
104 GLuint i;
105 for (i=0; i<n; i++) {
106 if (mask[i]) {
107 if (z[i] < zbuffer[i]) {
108 /* pass */
109 passed++;
110 }
111 else {
112 mask[i] = 0;
113 }
114 }
115 }
116 }
117 break;
118 case GL_LEQUAL:
119 if (ctx->Depth.Mask) {
120 /* Update Z buffer */
121 GLuint i;
122 for (i=0;i<n;i++) {
123 if (mask[i]) {
124 if (z[i] <= zbuffer[i]) {
125 zbuffer[i] = z[i];
126 passed++;
127 }
128 else {
129 mask[i] = 0;
130 }
131 }
132 }
133 }
134 else {
135 /* Don't update Z buffer */
136 GLuint i;
137 for (i=0;i<n;i++) {
138 if (mask[i]) {
139 if (z[i] <= zbuffer[i]) {
140 /* pass */
141 passed++;
142 }
143 else {
144 mask[i] = 0;
145 }
146 }
147 }
148 }
149 break;
150 case GL_GEQUAL:
151 if (ctx->Depth.Mask) {
152 /* Update Z buffer */
153 GLuint i;
154 for (i=0;i<n;i++) {
155 if (mask[i]) {
156 if (z[i] >= zbuffer[i]) {
157 zbuffer[i] = z[i];
158 passed++;
159 }
160 else {
161 mask[i] = 0;
162 }
163 }
164 }
165 }
166 else {
167 /* Don't update Z buffer */
168 GLuint i;
169 for (i=0;i<n;i++) {
170 if (mask[i]) {
171 if (z[i] >= zbuffer[i]) {
172 /* pass */
173 passed++;
174 }
175 else {
176 mask[i] = 0;
177 }
178 }
179 }
180 }
181 break;
182 case GL_GREATER:
183 if (ctx->Depth.Mask) {
184 /* Update Z buffer */
185 GLuint i;
186 for (i=0;i<n;i++) {
187 if (mask[i]) {
188 if (z[i] > zbuffer[i]) {
189 zbuffer[i] = z[i];
190 passed++;
191 }
192 else {
193 mask[i] = 0;
194 }
195 }
196 }
197 }
198 else {
199 /* Don't update Z buffer */
200 GLuint i;
201 for (i=0;i<n;i++) {
202 if (mask[i]) {
203 if (z[i] > zbuffer[i]) {
204 /* pass */
205 passed++;
206 }
207 else {
208 mask[i] = 0;
209 }
210 }
211 }
212 }
213 break;
214 case GL_NOTEQUAL:
215 if (ctx->Depth.Mask) {
216 /* Update Z buffer */
217 GLuint i;
218 for (i=0;i<n;i++) {
219 if (mask[i]) {
220 if (z[i] != zbuffer[i]) {
221 zbuffer[i] = z[i];
222 passed++;
223 }
224 else {
225 mask[i] = 0;
226 }
227 }
228 }
229 }
230 else {
231 /* Don't update Z buffer */
232 GLuint i;
233 for (i=0;i<n;i++) {
234 if (mask[i]) {
235 if (z[i] != zbuffer[i]) {
236 /* pass */
237 passed++;
238 }
239 else {
240 mask[i] = 0;
241 }
242 }
243 }
244 }
245 break;
246 case GL_EQUAL:
247 if (ctx->Depth.Mask) {
248 /* Update Z buffer */
249 GLuint i;
250 for (i=0;i<n;i++) {
251 if (mask[i]) {
252 if (z[i] == zbuffer[i]) {
253 zbuffer[i] = z[i];
254 passed++;
255 }
256 else {
257 mask[i] = 0;
258 }
259 }
260 }
261 }
262 else {
263 /* Don't update Z buffer */
264 GLuint i;
265 for (i=0;i<n;i++) {
266 if (mask[i]) {
267 if (z[i] == zbuffer[i]) {
268 /* pass */
269 passed++;
270 }
271 else {
272 mask[i] = 0;
273 }
274 }
275 }
276 }
277 break;
278 case GL_ALWAYS:
279 if (ctx->Depth.Mask) {
280 /* Update Z buffer */
281 GLuint i;
282 for (i=0;i<n;i++) {
283 if (mask[i]) {
284 zbuffer[i] = z[i];
285 passed++;
286 }
287 }
288 }
289 else {
290 /* Don't update Z buffer or mask */
291 passed = n;
292 }
293 break;
294 case GL_NEVER:
295 BZERO(mask, n * sizeof(GLubyte));
296 break;
297 default:
298 _mesa_problem(ctx, "Bad depth func in depth_test_span16");
299 }
300
301 return passed;
302 }
303
304
305 static GLuint
306 depth_test_span32( GLcontext *ctx, GLuint n,
307 GLuint zbuffer[], const GLdepth z[], GLubyte mask[] )
308 {
309 GLuint passed = 0;
310
311 /* switch cases ordered from most frequent to less frequent */
312 switch (ctx->Depth.Func) {
313 case GL_LESS:
314 if (ctx->Depth.Mask) {
315 /* Update Z buffer */
316 GLuint i;
317 for (i=0; i<n; i++) {
318 if (mask[i]) {
319 if (z[i] < zbuffer[i]) {
320 /* pass */
321 zbuffer[i] = z[i];
322 passed++;
323 }
324 else {
325 /* fail */
326 mask[i] = 0;
327 }
328 }
329 }
330 }
331 else {
332 /* Don't update Z buffer */
333 GLuint i;
334 for (i=0; i<n; i++) {
335 if (mask[i]) {
336 if (z[i] < zbuffer[i]) {
337 /* pass */
338 passed++;
339 }
340 else {
341 mask[i] = 0;
342 }
343 }
344 }
345 }
346 break;
347 case GL_LEQUAL:
348 if (ctx->Depth.Mask) {
349 /* Update Z buffer */
350 GLuint i;
351 for (i=0;i<n;i++) {
352 if (mask[i]) {
353 if (z[i] <= zbuffer[i]) {
354 zbuffer[i] = z[i];
355 passed++;
356 }
357 else {
358 mask[i] = 0;
359 }
360 }
361 }
362 }
363 else {
364 /* Don't update Z buffer */
365 GLuint i;
366 for (i=0;i<n;i++) {
367 if (mask[i]) {
368 if (z[i] <= zbuffer[i]) {
369 /* pass */
370 passed++;
371 }
372 else {
373 mask[i] = 0;
374 }
375 }
376 }
377 }
378 break;
379 case GL_GEQUAL:
380 if (ctx->Depth.Mask) {
381 /* Update Z buffer */
382 GLuint i;
383 for (i=0;i<n;i++) {
384 if (mask[i]) {
385 if (z[i] >= zbuffer[i]) {
386 zbuffer[i] = z[i];
387 passed++;
388 }
389 else {
390 mask[i] = 0;
391 }
392 }
393 }
394 }
395 else {
396 /* Don't update Z buffer */
397 GLuint i;
398 for (i=0;i<n;i++) {
399 if (mask[i]) {
400 if (z[i] >= zbuffer[i]) {
401 /* pass */
402 passed++;
403 }
404 else {
405 mask[i] = 0;
406 }
407 }
408 }
409 }
410 break;
411 case GL_GREATER:
412 if (ctx->Depth.Mask) {
413 /* Update Z buffer */
414 GLuint i;
415 for (i=0;i<n;i++) {
416 if (mask[i]) {
417 if (z[i] > zbuffer[i]) {
418 zbuffer[i] = z[i];
419 passed++;
420 }
421 else {
422 mask[i] = 0;
423 }
424 }
425 }
426 }
427 else {
428 /* Don't update Z buffer */
429 GLuint i;
430 for (i=0;i<n;i++) {
431 if (mask[i]) {
432 if (z[i] > zbuffer[i]) {
433 /* pass */
434 passed++;
435 }
436 else {
437 mask[i] = 0;
438 }
439 }
440 }
441 }
442 break;
443 case GL_NOTEQUAL:
444 if (ctx->Depth.Mask) {
445 /* Update Z buffer */
446 GLuint i;
447 for (i=0;i<n;i++) {
448 if (mask[i]) {
449 if (z[i] != zbuffer[i]) {
450 zbuffer[i] = z[i];
451 passed++;
452 }
453 else {
454 mask[i] = 0;
455 }
456 }
457 }
458 }
459 else {
460 /* Don't update Z buffer */
461 GLuint i;
462 for (i=0;i<n;i++) {
463 if (mask[i]) {
464 if (z[i] != zbuffer[i]) {
465 /* pass */
466 passed++;
467 }
468 else {
469 mask[i] = 0;
470 }
471 }
472 }
473 }
474 break;
475 case GL_EQUAL:
476 if (ctx->Depth.Mask) {
477 /* Update Z buffer */
478 GLuint i;
479 for (i=0;i<n;i++) {
480 if (mask[i]) {
481 if (z[i] == zbuffer[i]) {
482 zbuffer[i] = z[i];
483 passed++;
484 }
485 else {
486 mask[i] = 0;
487 }
488 }
489 }
490 }
491 else {
492 /* Don't update Z buffer */
493 GLuint i;
494 for (i=0;i<n;i++) {
495 if (mask[i]) {
496 if (z[i] == zbuffer[i]) {
497 /* pass */
498 passed++;
499 }
500 else {
501 mask[i] = 0;
502 }
503 }
504 }
505 }
506 break;
507 case GL_ALWAYS:
508 if (ctx->Depth.Mask) {
509 /* Update Z buffer */
510 GLuint i;
511 for (i=0;i<n;i++) {
512 if (mask[i]) {
513 zbuffer[i] = z[i];
514 passed++;
515 }
516 }
517 }
518 else {
519 /* Don't update Z buffer or mask */
520 passed = n;
521 }
522 break;
523 case GL_NEVER:
524 BZERO(mask, n * sizeof(GLubyte));
525 break;
526 default:
527 _mesa_problem(ctx, "Bad depth func in depth_test_span32");
528 }
529
530 return passed;
531 }
532
533
534
535
536 GLuint
537 _old_depth_test_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
538 const GLdepth z[], GLubyte mask[] )
539 {
540 SWcontext *swrast = SWRAST_CONTEXT(ctx);
541 if (swrast->Driver.ReadDepthSpan) {
542 /* hardware-based depth buffer */
543 GLdepth zbuffer[MAX_WIDTH];
544 GLuint passed;
545 (*swrast->Driver.ReadDepthSpan)(ctx, n, x, y, zbuffer);
546 passed = depth_test_span32(ctx, n, zbuffer, z, mask);
547 assert(swrast->Driver.WriteDepthSpan);
548 (*swrast->Driver.WriteDepthSpan)(ctx, n, x, y, zbuffer, mask);
549 return passed;
550 }
551 else {
552 /* software depth buffer */
553 if (ctx->Visual.depthBits <= 16) {
554 GLushort *zptr = (GLushort *) Z_ADDRESS16(ctx, x, y);
555 GLuint passed = depth_test_span16(ctx, n, zptr, z, mask);
556 return passed;
557 }
558 else {
559 GLuint *zptr = (GLuint *) Z_ADDRESS32(ctx, x, y);
560 GLuint passed = depth_test_span32(ctx, n, zptr, z, mask);
561 return passed;
562 }
563 }
564 }
565
566
567 /*
568 * Apply depth test to span of fragments. Hardware or software z buffer.
569 */
570 static GLuint
571 depth_test_span( GLcontext *ctx, struct sw_span *span)
572 {
573 SWcontext *swrast = SWRAST_CONTEXT(ctx);
574
575 ASSERT(span->arrayMask & SPAN_Z);
576
577 if (swrast->Driver.ReadDepthSpan) {
578 /* hardware-based depth buffer */
579 GLdepth zbuffer[MAX_WIDTH];
580 GLuint passed;
581 (*swrast->Driver.ReadDepthSpan)(ctx, span->end, span->x, span->y, zbuffer);
582 passed = depth_test_span32(ctx, span->end,
583 zbuffer, span->zArray, span->mask);
584 ASSERT(swrast->Driver.WriteDepthSpan);
585 (*swrast->Driver.WriteDepthSpan)(ctx, span->end, span->x, span->y, zbuffer, span->mask);
586 if (passed < span->end)
587 span->writeAll = GL_FALSE;
588 return passed;
589 }
590 else {
591 GLuint passed;
592 /* software depth buffer */
593 if (ctx->Visual.depthBits <= 16) {
594 GLushort *zptr = (GLushort *) Z_ADDRESS16(ctx, span->x, span->y);
595 passed = depth_test_span16(ctx, span->end, zptr, span->zArray, span->mask);
596 }
597 else {
598 GLuint *zptr = (GLuint *) Z_ADDRESS32(ctx, span->x, span->y);
599 passed = depth_test_span32(ctx, span->end, zptr, span->zArray, span->mask);
600 }
601 if (passed < span->end)
602 span->writeAll = GL_FALSE;
603 return passed;
604 }
605 }
606
607
608
609
610 /*
611 * Do depth testing for an array of fragments using software Z buffer.
612 */
613 static void
614 software_depth_test_pixels16( GLcontext *ctx, GLuint n,
615 const GLint x[], const GLint y[],
616 const GLdepth z[], GLubyte mask[] )
617 {
618 /* switch cases ordered from most frequent to less frequent */
619 switch (ctx->Depth.Func) {
620 case GL_LESS:
621 if (ctx->Depth.Mask) {
622 /* Update Z buffer */
623 GLuint i;
624 for (i=0; i<n; i++) {
625 if (mask[i]) {
626 GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
627 if (z[i] < *zptr) {
628 /* pass */
629 *zptr = z[i];
630 }
631 else {
632 /* fail */
633 mask[i] = 0;
634 }
635 }
636 }
637 }
638 else {
639 /* Don't update Z buffer */
640 GLuint i;
641 for (i=0; i<n; i++) {
642 if (mask[i]) {
643 GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
644 if (z[i] < *zptr) {
645 /* pass */
646 }
647 else {
648 /* fail */
649 mask[i] = 0;
650 }
651 }
652 }
653 }
654 break;
655 case GL_LEQUAL:
656 if (ctx->Depth.Mask) {
657 /* Update Z buffer */
658 GLuint i;
659 for (i=0; i<n; i++) {
660 if (mask[i]) {
661 GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
662 if (z[i] <= *zptr) {
663 /* pass */
664 *zptr = z[i];
665 }
666 else {
667 /* fail */
668 mask[i] = 0;
669 }
670 }
671 }
672 }
673 else {
674 /* Don't update Z buffer */
675 GLuint i;
676 for (i=0; i<n; i++) {
677 if (mask[i]) {
678 GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
679 if (z[i] <= *zptr) {
680 /* pass */
681 }
682 else {
683 /* fail */
684 mask[i] = 0;
685 }
686 }
687 }
688 }
689 break;
690 case GL_GEQUAL:
691 if (ctx->Depth.Mask) {
692 /* Update Z buffer */
693 GLuint i;
694 for (i=0; i<n; i++) {
695 if (mask[i]) {
696 GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
697 if (z[i] >= *zptr) {
698 /* pass */
699 *zptr = z[i];
700 }
701 else {
702 /* fail */
703 mask[i] = 0;
704 }
705 }
706 }
707 }
708 else {
709 /* Don't update Z buffer */
710 GLuint i;
711 for (i=0; i<n; i++) {
712 if (mask[i]) {
713 GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
714 if (z[i] >= *zptr) {
715 /* pass */
716 }
717 else {
718 /* fail */
719 mask[i] = 0;
720 }
721 }
722 }
723 }
724 break;
725 case GL_GREATER:
726 if (ctx->Depth.Mask) {
727 /* Update Z buffer */
728 GLuint i;
729 for (i=0; i<n; i++) {
730 if (mask[i]) {
731 GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
732 if (z[i] > *zptr) {
733 /* pass */
734 *zptr = z[i];
735 }
736 else {
737 /* fail */
738 mask[i] = 0;
739 }
740 }
741 }
742 }
743 else {
744 /* Don't update Z buffer */
745 GLuint i;
746 for (i=0; i<n; i++) {
747 if (mask[i]) {
748 GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
749 if (z[i] > *zptr) {
750 /* pass */
751 }
752 else {
753 /* fail */
754 mask[i] = 0;
755 }
756 }
757 }
758 }
759 break;
760 case GL_NOTEQUAL:
761 if (ctx->Depth.Mask) {
762 /* Update Z buffer */
763 GLuint i;
764 for (i=0; i<n; i++) {
765 if (mask[i]) {
766 GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
767 if (z[i] != *zptr) {
768 /* pass */
769 *zptr = z[i];
770 }
771 else {
772 /* fail */
773 mask[i] = 0;
774 }
775 }
776 }
777 }
778 else {
779 /* Don't update Z buffer */
780 GLuint i;
781 for (i=0; i<n; i++) {
782 if (mask[i]) {
783 GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
784 if (z[i] != *zptr) {
785 /* pass */
786 }
787 else {
788 /* fail */
789 mask[i] = 0;
790 }
791 }
792 }
793 }
794 break;
795 case GL_EQUAL:
796 if (ctx->Depth.Mask) {
797 /* Update Z buffer */
798 GLuint i;
799 for (i=0; i<n; i++) {
800 if (mask[i]) {
801 GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
802 if (z[i] == *zptr) {
803 /* pass */
804 *zptr = z[i];
805 }
806 else {
807 /* fail */
808 mask[i] = 0;
809 }
810 }
811 }
812 }
813 else {
814 /* Don't update Z buffer */
815 GLuint i;
816 for (i=0; i<n; i++) {
817 if (mask[i]) {
818 GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
819 if (z[i] == *zptr) {
820 /* pass */
821 }
822 else {
823 /* fail */
824 mask[i] = 0;
825 }
826 }
827 }
828 }
829 break;
830 case GL_ALWAYS:
831 if (ctx->Depth.Mask) {
832 /* Update Z buffer */
833 GLuint i;
834 for (i=0; i<n; i++) {
835 if (mask[i]) {
836 GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
837 *zptr = z[i];
838 }
839 }
840 }
841 else {
842 /* Don't update Z buffer or mask */
843 }
844 break;
845 case GL_NEVER:
846 /* depth test never passes */
847 BZERO(mask, n * sizeof(GLubyte));
848 break;
849 default:
850 _mesa_problem(ctx, "Bad depth func in software_depth_test_pixels");
851 }
852 }
853
854
855
856 /*
857 * Do depth testing for an array of fragments using software Z buffer.
858 */
859 static void
860 software_depth_test_pixels32( GLcontext *ctx, GLuint n,
861 const GLint x[], const GLint y[],
862 const GLdepth z[], GLubyte mask[] )
863 {
864 /* switch cases ordered from most frequent to less frequent */
865 switch (ctx->Depth.Func) {
866 case GL_LESS:
867 if (ctx->Depth.Mask) {
868 /* Update Z buffer */
869 GLuint i;
870 for (i=0; i<n; i++) {
871 if (mask[i]) {
872 GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
873 if (z[i] < *zptr) {
874 /* pass */
875 *zptr = z[i];
876 }
877 else {
878 /* fail */
879 mask[i] = 0;
880 }
881 }
882 }
883 }
884 else {
885 /* Don't update Z buffer */
886 GLuint i;
887 for (i=0; i<n; i++) {
888 if (mask[i]) {
889 GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
890 if (z[i] < *zptr) {
891 /* pass */
892 }
893 else {
894 /* fail */
895 mask[i] = 0;
896 }
897 }
898 }
899 }
900 break;
901 case GL_LEQUAL:
902 if (ctx->Depth.Mask) {
903 /* Update Z buffer */
904 GLuint i;
905 for (i=0; i<n; i++) {
906 if (mask[i]) {
907 GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
908 if (z[i] <= *zptr) {
909 /* pass */
910 *zptr = z[i];
911 }
912 else {
913 /* fail */
914 mask[i] = 0;
915 }
916 }
917 }
918 }
919 else {
920 /* Don't update Z buffer */
921 GLuint i;
922 for (i=0; i<n; i++) {
923 if (mask[i]) {
924 GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
925 if (z[i] <= *zptr) {
926 /* pass */
927 }
928 else {
929 /* fail */
930 mask[i] = 0;
931 }
932 }
933 }
934 }
935 break;
936 case GL_GEQUAL:
937 if (ctx->Depth.Mask) {
938 /* Update Z buffer */
939 GLuint i;
940 for (i=0; i<n; i++) {
941 if (mask[i]) {
942 GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
943 if (z[i] >= *zptr) {
944 /* pass */
945 *zptr = z[i];
946 }
947 else {
948 /* fail */
949 mask[i] = 0;
950 }
951 }
952 }
953 }
954 else {
955 /* Don't update Z buffer */
956 GLuint i;
957 for (i=0; i<n; i++) {
958 if (mask[i]) {
959 GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
960 if (z[i] >= *zptr) {
961 /* pass */
962 }
963 else {
964 /* fail */
965 mask[i] = 0;
966 }
967 }
968 }
969 }
970 break;
971 case GL_GREATER:
972 if (ctx->Depth.Mask) {
973 /* Update Z buffer */
974 GLuint i;
975 for (i=0; i<n; i++) {
976 if (mask[i]) {
977 GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
978 if (z[i] > *zptr) {
979 /* pass */
980 *zptr = z[i];
981 }
982 else {
983 /* fail */
984 mask[i] = 0;
985 }
986 }
987 }
988 }
989 else {
990 /* Don't update Z buffer */
991 GLuint i;
992 for (i=0; i<n; i++) {
993 if (mask[i]) {
994 GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
995 if (z[i] > *zptr) {
996 /* pass */
997 }
998 else {
999 /* fail */
1000 mask[i] = 0;
1001 }
1002 }
1003 }
1004 }
1005 break;
1006 case GL_NOTEQUAL:
1007 if (ctx->Depth.Mask) {
1008 /* Update Z buffer */
1009 GLuint i;
1010 for (i=0; i<n; i++) {
1011 if (mask[i]) {
1012 GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
1013 if (z[i] != *zptr) {
1014 /* pass */
1015 *zptr = z[i];
1016 }
1017 else {
1018 /* fail */
1019 mask[i] = 0;
1020 }
1021 }
1022 }
1023 }
1024 else {
1025 /* Don't update Z buffer */
1026 GLuint i;
1027 for (i=0; i<n; i++) {
1028 if (mask[i]) {
1029 GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
1030 if (z[i] != *zptr) {
1031 /* pass */
1032 }
1033 else {
1034 /* fail */
1035 mask[i] = 0;
1036 }
1037 }
1038 }
1039 }
1040 break;
1041 case GL_EQUAL:
1042 if (ctx->Depth.Mask) {
1043 /* Update Z buffer */
1044 GLuint i;
1045 for (i=0; i<n; i++) {
1046 if (mask[i]) {
1047 GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
1048 if (z[i] == *zptr) {
1049 /* pass */
1050 *zptr = z[i];
1051 }
1052 else {
1053 /* fail */
1054 mask[i] = 0;
1055 }
1056 }
1057 }
1058 }
1059 else {
1060 /* Don't update Z buffer */
1061 GLuint i;
1062 for (i=0; i<n; i++) {
1063 if (mask[i]) {
1064 GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
1065 if (z[i] == *zptr) {
1066 /* pass */
1067 }
1068 else {
1069 /* fail */
1070 mask[i] = 0;
1071 }
1072 }
1073 }
1074 }
1075 break;
1076 case GL_ALWAYS:
1077 if (ctx->Depth.Mask) {
1078 /* Update Z buffer */
1079 GLuint i;
1080 for (i=0; i<n; i++) {
1081 if (mask[i]) {
1082 GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
1083 *zptr = z[i];
1084 }
1085 }
1086 }
1087 else {
1088 /* Don't update Z buffer or mask */
1089 }
1090 break;
1091 case GL_NEVER:
1092 /* depth test never passes */
1093 BZERO(mask, n * sizeof(GLubyte));
1094 break;
1095 default:
1096 _mesa_problem(ctx, "Bad depth func in software_depth_test_pixels");
1097 }
1098 }
1099
1100
1101
1102 /*
1103 * Do depth testing for an array of pixels using hardware Z buffer.
1104 * Input/output: zbuffer - array of depth values from Z buffer
1105 * Input: z - array of fragment z values.
1106 */
1107 static void
1108 hardware_depth_test_pixels( GLcontext *ctx, GLuint n, GLdepth zbuffer[],
1109 const GLdepth z[], GLubyte mask[] )
1110 {
1111 /* switch cases ordered from most frequent to less frequent */
1112 switch (ctx->Depth.Func) {
1113 case GL_LESS:
1114 if (ctx->Depth.Mask) {
1115 /* Update Z buffer */
1116 GLuint i;
1117 for (i=0; i<n; i++) {
1118 if (mask[i]) {
1119 if (z[i] < zbuffer[i]) {
1120 /* pass */
1121 zbuffer[i] = z[i];
1122 }
1123 else {
1124 /* fail */
1125 mask[i] = 0;
1126 }
1127 }
1128 }
1129 }
1130 else {
1131 /* Don't update Z buffer */
1132 GLuint i;
1133 for (i=0; i<n; i++) {
1134 if (mask[i]) {
1135 if (z[i] < zbuffer[i]) {
1136 /* pass */
1137 }
1138 else {
1139 /* fail */
1140 mask[i] = 0;
1141 }
1142 }
1143 }
1144 }
1145 break;
1146 case GL_LEQUAL:
1147 if (ctx->Depth.Mask) {
1148 /* Update Z buffer */
1149 GLuint i;
1150 for (i=0; i<n; i++) {
1151 if (mask[i]) {
1152 if (z[i] <= zbuffer[i]) {
1153 /* pass */
1154 zbuffer[i] = z[i];
1155 }
1156 else {
1157 /* fail */
1158 mask[i] = 0;
1159 }
1160 }
1161 }
1162 }
1163 else {
1164 /* Don't update Z buffer */
1165 GLuint i;
1166 for (i=0; i<n; i++) {
1167 if (mask[i]) {
1168 if (z[i] <= zbuffer[i]) {
1169 /* pass */
1170 }
1171 else {
1172 /* fail */
1173 mask[i] = 0;
1174 }
1175 }
1176 }
1177 }
1178 break;
1179 case GL_GEQUAL:
1180 if (ctx->Depth.Mask) {
1181 /* Update Z buffer */
1182 GLuint i;
1183 for (i=0; i<n; i++) {
1184 if (mask[i]) {
1185 if (z[i] >= zbuffer[i]) {
1186 /* pass */
1187 zbuffer[i] = z[i];
1188 }
1189 else {
1190 /* fail */
1191 mask[i] = 0;
1192 }
1193 }
1194 }
1195 }
1196 else {
1197 /* Don't update Z buffer */
1198 GLuint i;
1199 for (i=0; i<n; i++) {
1200 if (mask[i]) {
1201 if (z[i] >= zbuffer[i]) {
1202 /* pass */
1203 }
1204 else {
1205 /* fail */
1206 mask[i] = 0;
1207 }
1208 }
1209 }
1210 }
1211 break;
1212 case GL_GREATER:
1213 if (ctx->Depth.Mask) {
1214 /* Update Z buffer */
1215 GLuint i;
1216 for (i=0; i<n; i++) {
1217 if (mask[i]) {
1218 if (z[i] > zbuffer[i]) {
1219 /* pass */
1220 zbuffer[i] = z[i];
1221 }
1222 else {
1223 /* fail */
1224 mask[i] = 0;
1225 }
1226 }
1227 }
1228 }
1229 else {
1230 /* Don't update Z buffer */
1231 GLuint i;
1232 for (i=0; i<n; i++) {
1233 if (mask[i]) {
1234 if (z[i] > zbuffer[i]) {
1235 /* pass */
1236 }
1237 else {
1238 /* fail */
1239 mask[i] = 0;
1240 }
1241 }
1242 }
1243 }
1244 break;
1245 case GL_NOTEQUAL:
1246 if (ctx->Depth.Mask) {
1247 /* Update Z buffer */
1248 GLuint i;
1249 for (i=0; i<n; i++) {
1250 if (mask[i]) {
1251 if (z[i] != zbuffer[i]) {
1252 /* pass */
1253 zbuffer[i] = z[i];
1254 }
1255 else {
1256 /* fail */
1257 mask[i] = 0;
1258 }
1259 }
1260 }
1261 }
1262 else {
1263 /* Don't update Z buffer */
1264 GLuint i;
1265 for (i=0; i<n; i++) {
1266 if (mask[i]) {
1267 if (z[i] != zbuffer[i]) {
1268 /* pass */
1269 }
1270 else {
1271 /* fail */
1272 mask[i] = 0;
1273 }
1274 }
1275 }
1276 }
1277 break;
1278 case GL_EQUAL:
1279 if (ctx->Depth.Mask) {
1280 /* Update Z buffer */
1281 GLuint i;
1282 for (i=0; i<n; i++) {
1283 if (mask[i]) {
1284 if (z[i] == zbuffer[i]) {
1285 /* pass */
1286 zbuffer[i] = z[i];
1287 }
1288 else {
1289 /* fail */
1290 mask[i] = 0;
1291 }
1292 }
1293 }
1294 }
1295 else {
1296 /* Don't update Z buffer */
1297 GLuint i;
1298 for (i=0; i<n; i++) {
1299 if (mask[i]) {
1300 if (z[i] == zbuffer[i]) {
1301 /* pass */
1302 }
1303 else {
1304 /* fail */
1305 mask[i] = 0;
1306 }
1307 }
1308 }
1309 }
1310 break;
1311 case GL_ALWAYS:
1312 if (ctx->Depth.Mask) {
1313 /* Update Z buffer */
1314 GLuint i;
1315 for (i=0; i<n; i++) {
1316 if (mask[i]) {
1317 zbuffer[i] = z[i];
1318 }
1319 }
1320 }
1321 else {
1322 /* Don't update Z buffer or mask */
1323 }
1324 break;
1325 case GL_NEVER:
1326 /* depth test never passes */
1327 BZERO(mask, n * sizeof(GLubyte));
1328 break;
1329 default:
1330 _mesa_problem(ctx, "Bad depth func in hardware_depth_test_pixels");
1331 }
1332 }
1333
1334 void
1335 _mesa_depth_test_pixels( GLcontext *ctx,
1336 GLuint n, const GLint x[], const GLint y[],
1337 const GLdepth z[], GLubyte mask[] )
1338 {
1339 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1340 if (swrast->Driver.ReadDepthPixels) {
1341 /* read depth values from hardware Z buffer */
1342 GLdepth zbuffer[MAX_WIDTH];
1343 (*swrast->Driver.ReadDepthPixels)(ctx, n, x, y, zbuffer);
1344
1345 hardware_depth_test_pixels( ctx, n, zbuffer, z, mask );
1346
1347 /* update hardware Z buffer with new values */
1348 assert(swrast->Driver.WriteDepthPixels);
1349 (*swrast->Driver.WriteDepthPixels)(ctx, n, x, y, zbuffer, mask );
1350 }
1351 else {
1352 /* software depth testing */
1353 if (ctx->Visual.depthBits <= 16)
1354 software_depth_test_pixels16(ctx, n, x, y, z, mask);
1355 else
1356 software_depth_test_pixels32(ctx, n, x, y, z, mask);
1357 }
1358 }
1359
1360
1361
1362 GLuint
1363 _mesa_depth_test_span( GLcontext *ctx, struct sw_span *span)
1364 {
1365 if (span->arrayMask & SPAN_XY) {
1366 _mesa_depth_test_pixels(ctx, span->end,
1367 span->xArray, span->yArray,
1368 span->zArray, span->mask);
1369 return 1;
1370 }
1371 else {
1372 return depth_test_span(ctx, span);
1373 }
1374 }
1375
1376
1377
1378 /**********************************************************************/
1379 /***** Read Depth Buffer *****/
1380 /**********************************************************************/
1381
1382
1383 /*
1384 * Read a span of depth values from the depth buffer.
1385 * This function does clipping before calling the device driver function.
1386 */
1387 void
1388 _mesa_read_depth_span( GLcontext *ctx,
1389 GLint n, GLint x, GLint y, GLdepth depth[] )
1390 {
1391 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1392
1393 if (y < 0 || y >= ctx->DrawBuffer->Height ||
1394 x + (GLint) n <= 0 || x >= ctx->DrawBuffer->Width) {
1395 /* span is completely outside framebuffer */
1396 GLint i;
1397 for (i = 0; i < n; i++)
1398 depth[i] = 0;
1399 return;
1400 }
1401
1402 if (x < 0) {
1403 GLint dx = -x;
1404 GLint i;
1405 for (i = 0; i < dx; i++)
1406 depth[i] = 0;
1407 x = 0;
1408 n -= dx;
1409 depth += dx;
1410 }
1411 if (x + n > ctx->DrawBuffer->Width) {
1412 GLint dx = x + n - ctx->DrawBuffer->Width;
1413 GLint i;
1414 for (i = 0; i < dx; i++)
1415 depth[n - i - 1] = 0;
1416 n -= dx;
1417 }
1418 if (n <= 0) {
1419 return;
1420 }
1421
1422 if (ctx->DrawBuffer->DepthBuffer) {
1423 /* read from software depth buffer */
1424 if (ctx->Visual.depthBits <= 16) {
1425 const GLushort *zptr = Z_ADDRESS16( ctx, x, y );
1426 GLint i;
1427 for (i = 0; i < n; i++) {
1428 depth[i] = zptr[i];
1429 }
1430 }
1431 else {
1432 const GLuint *zptr = Z_ADDRESS32( ctx, x, y );
1433 GLint i;
1434 for (i = 0; i < n; i++) {
1435 depth[i] = zptr[i];
1436 }
1437 }
1438 }
1439 else if (swrast->Driver.ReadDepthSpan) {
1440 /* read from hardware depth buffer */
1441 (*swrast->Driver.ReadDepthSpan)( ctx, n, x, y, depth );
1442 }
1443 else {
1444 /* no depth buffer */
1445 BZERO(depth, n * sizeof(GLfloat));
1446 }
1447
1448 }
1449
1450
1451
1452
1453 /*
1454 * Return a span of depth values from the depth buffer as floats in [0,1].
1455 * This is used for both hardware and software depth buffers.
1456 * Input: n - how many pixels
1457 * x,y - location of first pixel
1458 * Output: depth - the array of depth values
1459 */
1460 void
1461 _mesa_read_depth_span_float( GLcontext *ctx,
1462 GLint n, GLint x, GLint y, GLfloat depth[] )
1463 {
1464 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1465 const GLfloat scale = 1.0F / ctx->DepthMaxF;
1466
1467 if (y < 0 || y >= ctx->DrawBuffer->Height ||
1468 x + (GLint) n <= 0 || x >= ctx->DrawBuffer->Width) {
1469 /* span is completely outside framebuffer */
1470 GLint i;
1471 for (i = 0; i < n; i++)
1472 depth[i] = 0.0F;
1473 return;
1474 }
1475
1476 if (x < 0) {
1477 GLint dx = -x;
1478 GLint i;
1479 for (i = 0; i < dx; i++)
1480 depth[i] = 0.0F;
1481 n -= dx;
1482 x = 0;
1483 }
1484 if (x + n > ctx->DrawBuffer->Width) {
1485 GLint dx = x + n - ctx->DrawBuffer->Width;
1486 GLint i;
1487 for (i = 0; i < dx; i++)
1488 depth[n - i - 1] = 0.0F;
1489 n -= dx;
1490 }
1491 if (n <= 0) {
1492 return;
1493 }
1494
1495 if (ctx->DrawBuffer->DepthBuffer) {
1496 /* read from software depth buffer */
1497 if (ctx->Visual.depthBits <= 16) {
1498 const GLushort *zptr = Z_ADDRESS16( ctx, x, y );
1499 GLint i;
1500 for (i = 0; i < n; i++) {
1501 depth[i] = (GLfloat) zptr[i] * scale;
1502 }
1503 }
1504 else {
1505 const GLuint *zptr = Z_ADDRESS32( ctx, x, y );
1506 GLint i;
1507 for (i = 0; i < n; i++) {
1508 depth[i] = (GLfloat) zptr[i] * scale;
1509 }
1510 }
1511 }
1512 else if (swrast->Driver.ReadDepthSpan) {
1513 /* read from hardware depth buffer */
1514 GLdepth d[MAX_WIDTH];
1515 GLint i;
1516 assert(n <= MAX_WIDTH);
1517 (*swrast->Driver.ReadDepthSpan)( ctx, n, x, y, d );
1518 for (i = 0; i < n; i++) {
1519 depth[i] = d[i] * scale;
1520 }
1521 }
1522 else {
1523 /* no depth buffer */
1524 BZERO(depth, n * sizeof(GLfloat));
1525 }
1526 }
1527
1528
1529
1530 /**********************************************************************/
1531 /***** Allocate and Clear Depth Buffer *****/
1532 /**********************************************************************/
1533
1534
1535
1536 /*
1537 * Allocate a new depth buffer. If there's already a depth buffer allocated
1538 * it will be free()'d. The new depth buffer will be uniniitalized.
1539 * This function is only called through Driver.alloc_depth_buffer.
1540 */
1541 void
1542 _mesa_alloc_depth_buffer( GLcontext *ctx )
1543 {
1544 /* deallocate current depth buffer if present */
1545 if (ctx->DrawBuffer->UseSoftwareDepthBuffer) {
1546 GLint bytesPerValue;
1547
1548 if (ctx->DrawBuffer->DepthBuffer) {
1549 FREE(ctx->DrawBuffer->DepthBuffer);
1550 ctx->DrawBuffer->DepthBuffer = NULL;
1551 }
1552
1553 /* allocate new depth buffer, but don't initialize it */
1554 if (ctx->Visual.depthBits <= 16)
1555 bytesPerValue = sizeof(GLushort);
1556 else
1557 bytesPerValue = sizeof(GLuint);
1558
1559 ctx->DrawBuffer->DepthBuffer = MALLOC( ctx->DrawBuffer->Width
1560 * ctx->DrawBuffer->Height
1561 * bytesPerValue );
1562
1563 if (!ctx->DrawBuffer->DepthBuffer) {
1564 /* out of memory */
1565 ctx->Depth.Test = GL_FALSE;
1566 ctx->NewState |= _NEW_DEPTH;
1567 _mesa_error( ctx, GL_OUT_OF_MEMORY, "Couldn't allocate depth buffer" );
1568 }
1569 }
1570 }
1571
1572
1573
1574
1575 /*
1576 * Clear the depth buffer. If the depth buffer doesn't exist yet we'll
1577 * allocate it now.
1578 * This function is only called through Driver.clear_depth_buffer.
1579 */
1580 void
1581 _mesa_clear_depth_buffer( GLcontext *ctx )
1582 {
1583 if (ctx->Visual.depthBits == 0
1584 || !ctx->DrawBuffer->DepthBuffer
1585 || !ctx->Depth.Mask) {
1586 /* no depth buffer, or writing to it is disabled */
1587 return;
1588 }
1589
1590 /* The loops in this function have been written so the IRIX 5.3
1591 * C compiler can unroll them. Hopefully other compilers can too!
1592 */
1593
1594 if (ctx->Scissor.Enabled) {
1595 /* only clear scissor region */
1596 if (ctx->Visual.depthBits <= 16) {
1597 const GLushort clearValue = (GLushort) (ctx->Depth.Clear * ctx->DepthMax);
1598 const GLint rows = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
1599 const GLint cols = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
1600 const GLint rowStride = ctx->DrawBuffer->Width;
1601 GLushort *dRow = (GLushort *) ctx->DrawBuffer->DepthBuffer
1602 + ctx->DrawBuffer->_Ymin * rowStride + ctx->DrawBuffer->_Xmin;
1603 GLint i, j;
1604 for (i = 0; i < rows; i++) {
1605 for (j = 0; j < cols; j++) {
1606 dRow[j] = clearValue;
1607 }
1608 dRow += rowStride;
1609 }
1610 }
1611 else {
1612 const GLuint clearValue = (GLuint) (ctx->Depth.Clear * ctx->DepthMax);
1613 const GLint rows = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
1614 const GLint cols = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
1615 const GLint rowStride = ctx->DrawBuffer->Width;
1616 GLuint *dRow = (GLuint *) ctx->DrawBuffer->DepthBuffer
1617 + ctx->DrawBuffer->_Ymin * rowStride + ctx->DrawBuffer->_Xmin;
1618 GLint i, j;
1619 for (i = 0; i < rows; i++) {
1620 for (j = 0; j < cols; j++) {
1621 dRow[j] = clearValue;
1622 }
1623 dRow += rowStride;
1624 }
1625 }
1626 }
1627 else {
1628 /* clear whole buffer */
1629 if (ctx->Visual.depthBits <= 16) {
1630 const GLushort clearValue = (GLushort) (ctx->Depth.Clear * ctx->DepthMax);
1631 if ((clearValue & 0xff) == (clearValue >> 8)) {
1632 if (clearValue == 0) {
1633 BZERO(ctx->DrawBuffer->DepthBuffer,
1634 2*ctx->DrawBuffer->Width*ctx->DrawBuffer->Height);
1635 }
1636 else {
1637 /* lower and upper bytes of clear_value are same, use MEMSET */
1638 MEMSET( ctx->DrawBuffer->DepthBuffer, clearValue & 0xff,
1639 2 * ctx->DrawBuffer->Width * ctx->DrawBuffer->Height);
1640 }
1641 }
1642 else {
1643 GLushort *d = (GLushort *) ctx->DrawBuffer->DepthBuffer;
1644 GLint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
1645 while (n >= 16) {
1646 d[0] = clearValue; d[1] = clearValue;
1647 d[2] = clearValue; d[3] = clearValue;
1648 d[4] = clearValue; d[5] = clearValue;
1649 d[6] = clearValue; d[7] = clearValue;
1650 d[8] = clearValue; d[9] = clearValue;
1651 d[10] = clearValue; d[11] = clearValue;
1652 d[12] = clearValue; d[13] = clearValue;
1653 d[14] = clearValue; d[15] = clearValue;
1654 d += 16;
1655 n -= 16;
1656 }
1657 while (n > 0) {
1658 *d++ = clearValue;
1659 n--;
1660 }
1661 }
1662 }
1663 else {
1664 /* >16 bit depth buffer */
1665 const GLuint clearValue = (GLuint) (ctx->Depth.Clear * ctx->DepthMax);
1666 if (clearValue == 0) {
1667 BZERO(ctx->DrawBuffer->DepthBuffer,
1668 ctx->DrawBuffer->Width*ctx->DrawBuffer->Height*sizeof(GLuint));
1669 }
1670 else {
1671 GLint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
1672 GLuint *d = (GLuint *) ctx->DrawBuffer->DepthBuffer;
1673 while (n >= 16) {
1674 d[0] = clearValue; d[1] = clearValue;
1675 d[2] = clearValue; d[3] = clearValue;
1676 d[4] = clearValue; d[5] = clearValue;
1677 d[6] = clearValue; d[7] = clearValue;
1678 d[8] = clearValue; d[9] = clearValue;
1679 d[10] = clearValue; d[11] = clearValue;
1680 d[12] = clearValue; d[13] = clearValue;
1681 d[14] = clearValue; d[15] = clearValue;
1682 d += 16;
1683 n -= 16;
1684 }
1685 while (n > 0) {
1686 *d++ = clearValue;
1687 n--;
1688 }
1689 }
1690 }
1691 }
1692 }