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