1 /* $Id: depth.c,v 1.7 1999/10/13 18:42:50 brianp 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.
28 /* $XFree86: xc/lib/GL/mesa/src/depth.c,v 1.3 1999/04/04 00:20:22 dawes Exp $ */
31 * Depth buffer functions
43 #include "GL/xf86glx.h"
51 #include "GL/xf86glx.h"
57 /**********************************************************************/
58 /***** API Functions *****/
59 /**********************************************************************/
63 void gl_ClearDepth( GLcontext
* ctx
, GLclampd depth
)
65 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glClearDepth");
66 ctx
->Depth
.Clear
= (GLfloat
) CLAMP( depth
, 0.0, 1.0 );
67 if (ctx
->Driver
.ClearDepth
)
68 (*ctx
->Driver
.ClearDepth
)( ctx
, ctx
->Depth
.Clear
);
73 void gl_DepthFunc( GLcontext
* ctx
, GLenum func
)
75 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glDepthFunc");
77 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
78 fprintf(stderr
, "glDepthFunc %s\n", gl_lookup_enum_by_nr(func
));
81 case GL_LESS
: /* (default) pass if incoming z < stored z */
88 if (ctx
->Depth
.Func
!= func
) {
89 ctx
->Depth
.Func
= func
;
90 ctx
->NewState
|= NEW_RASTER_OPS
;
91 ctx
->TriangleCaps
&= ~DD_Z_NEVER
;
92 if (ctx
->Driver
.DepthFunc
) {
93 (*ctx
->Driver
.DepthFunc
)( ctx
, func
);
98 if (ctx
->Depth
.Func
!= func
) {
99 ctx
->Depth
.Func
= func
;
100 ctx
->NewState
|= NEW_RASTER_OPS
;
101 ctx
->TriangleCaps
|= DD_Z_NEVER
;
102 if (ctx
->Driver
.DepthFunc
) {
103 (*ctx
->Driver
.DepthFunc
)( ctx
, func
);
108 gl_error( ctx
, GL_INVALID_ENUM
, "glDepth.Func" );
114 void gl_DepthMask( GLcontext
* ctx
, GLboolean flag
)
116 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
, "glDepthMask");
118 if (MESA_VERBOSE
& (VERBOSE_API
|VERBOSE_TEXTURE
))
119 fprintf(stderr
, "glDepthMask %d\n", flag
);
122 * GL_TRUE indicates depth buffer writing is enabled (default)
123 * GL_FALSE indicates depth buffer writing is disabled
125 if (ctx
->Depth
.Mask
!= flag
) {
126 ctx
->Depth
.Mask
= flag
;
127 ctx
->NewState
|= NEW_RASTER_OPS
;
128 if (ctx
->Driver
.DepthMask
) {
129 (*ctx
->Driver
.DepthMask
)( ctx
, flag
);
136 /**********************************************************************/
137 /***** Depth Testing Functions *****/
138 /**********************************************************************/
142 * Depth test horizontal spans of fragments. These functions are called
143 * via ctx->Driver.depth_test_span only.
145 * Input: n - number of pixels in the span
146 * x, y - location of leftmost pixel in span in window coords
147 * z - array [n] of integer depth values
148 * In/Out: mask - array [n] of flags (1=draw pixel, 0=don't draw)
149 * Return: number of pixels which passed depth test
154 * glDepthFunc( any ) and glDepthMask( GL_TRUE or GL_FALSE ).
156 GLuint
gl_depth_test_span_generic( GLcontext
* ctx
,
157 GLuint n
, GLint x
, GLint y
,
161 GLdepth
*zptr
= Z_ADDRESS( ctx
, x
, y
);
166 /* switch cases ordered from most frequent to less frequent */
167 switch (ctx
->Depth
.Func
) {
169 if (ctx
->Depth
.Mask
) {
170 /* Update Z buffer */
171 for (i
=0; i
<n
; i
++,zptr
++,m
++) {
186 /* Don't update Z buffer */
187 for (i
=0; i
<n
; i
++,zptr
++,m
++) {
201 if (ctx
->Depth
.Mask
) {
202 /* Update Z buffer */
203 for (i
=0;i
<n
;i
++,zptr
++,m
++) {
216 /* Don't update Z buffer */
217 for (i
=0;i
<n
;i
++,zptr
++,m
++) {
231 if (ctx
->Depth
.Mask
) {
232 /* Update Z buffer */
233 for (i
=0;i
<n
;i
++,zptr
++,m
++) {
246 /* Don't update Z buffer */
247 for (i
=0;i
<n
;i
++,zptr
++,m
++) {
261 if (ctx
->Depth
.Mask
) {
262 /* Update Z buffer */
263 for (i
=0;i
<n
;i
++,zptr
++,m
++) {
276 /* Don't update Z buffer */
277 for (i
=0;i
<n
;i
++,zptr
++,m
++) {
291 if (ctx
->Depth
.Mask
) {
292 /* Update Z buffer */
293 for (i
=0;i
<n
;i
++,zptr
++,m
++) {
306 /* Don't update Z buffer */
307 for (i
=0;i
<n
;i
++,zptr
++,m
++) {
321 if (ctx
->Depth
.Mask
) {
322 /* Update Z buffer */
323 for (i
=0;i
<n
;i
++,zptr
++,m
++) {
336 /* Don't update Z buffer */
337 for (i
=0;i
<n
;i
++,zptr
++,m
++) {
351 if (ctx
->Depth
.Mask
) {
352 /* Update Z buffer */
353 for (i
=0;i
<n
;i
++,zptr
++,m
++) {
361 /* Don't update Z buffer or mask */
371 gl_problem(ctx
, "Bad depth func in gl_depth_test_span_generic");
380 * glDepthFunc(GL_LESS) and glDepthMask(GL_TRUE).
382 GLuint
gl_depth_test_span_less( GLcontext
* ctx
,
383 GLuint n
, GLint x
, GLint y
, const GLdepth z
[],
386 GLdepth
*zptr
= Z_ADDRESS( ctx
, x
, y
);
390 for (i
=0; i
<n
; i
++) {
392 if (z
[i
] < zptr
[i
]) {
408 * glDepthFunc(GL_GREATER) and glDepthMask(GL_TRUE).
410 GLuint
gl_depth_test_span_greater( GLcontext
* ctx
,
411 GLuint n
, GLint x
, GLint y
,
415 GLdepth
*zptr
= Z_ADDRESS( ctx
, x
, y
);
419 for (i
=0; i
<n
; i
++) {
421 if (z
[i
] > zptr
[i
]) {
438 * Depth test an array of randomly positioned fragments.
442 #define ZADDR_SETUP GLdepth *depthbuffer = ctx->Buffer->Depth; \
443 GLint width = ctx->Buffer->Width;
445 #define ZADDR( X, Y ) (depthbuffer + (Y) * width + (X) )
450 * glDepthFunc( any ) and glDepthMask( GL_TRUE or GL_FALSE ).
452 void gl_depth_test_pixels_generic( GLcontext
* ctx
,
453 GLuint n
, const GLint x
[], const GLint y
[],
454 const GLdepth z
[], GLubyte mask
[] )
456 register GLdepth
*zptr
;
459 /* switch cases ordered from most frequent to less frequent */
460 switch (ctx
->Depth
.Func
) {
462 if (ctx
->Depth
.Mask
) {
463 /* Update Z buffer */
464 for (i
=0; i
<n
; i
++) {
466 zptr
= Z_ADDRESS(ctx
,x
[i
],y
[i
]);
479 /* Don't update Z buffer */
480 for (i
=0; i
<n
; i
++) {
482 zptr
= Z_ADDRESS(ctx
,x
[i
],y
[i
]);
495 if (ctx
->Depth
.Mask
) {
496 /* Update Z buffer */
497 for (i
=0; i
<n
; i
++) {
499 zptr
= Z_ADDRESS(ctx
,x
[i
],y
[i
]);
512 /* Don't update Z buffer */
513 for (i
=0; i
<n
; i
++) {
515 zptr
= Z_ADDRESS(ctx
,x
[i
],y
[i
]);
528 if (ctx
->Depth
.Mask
) {
529 /* Update Z buffer */
530 for (i
=0; i
<n
; i
++) {
532 zptr
= Z_ADDRESS(ctx
,x
[i
],y
[i
]);
545 /* Don't update Z buffer */
546 for (i
=0; i
<n
; i
++) {
548 zptr
= Z_ADDRESS(ctx
,x
[i
],y
[i
]);
561 if (ctx
->Depth
.Mask
) {
562 /* Update Z buffer */
563 for (i
=0; i
<n
; i
++) {
565 zptr
= Z_ADDRESS(ctx
,x
[i
],y
[i
]);
578 /* Don't update Z buffer */
579 for (i
=0; i
<n
; i
++) {
581 zptr
= Z_ADDRESS(ctx
,x
[i
],y
[i
]);
594 if (ctx
->Depth
.Mask
) {
595 /* Update Z buffer */
596 for (i
=0; i
<n
; i
++) {
598 zptr
= Z_ADDRESS(ctx
,x
[i
],y
[i
]);
611 /* Don't update Z buffer */
612 for (i
=0; i
<n
; i
++) {
614 zptr
= Z_ADDRESS(ctx
,x
[i
],y
[i
]);
627 if (ctx
->Depth
.Mask
) {
628 /* Update Z buffer */
629 for (i
=0; i
<n
; i
++) {
631 zptr
= Z_ADDRESS(ctx
,x
[i
],y
[i
]);
644 /* Don't update Z buffer */
645 for (i
=0; i
<n
; i
++) {
647 zptr
= Z_ADDRESS(ctx
,x
[i
],y
[i
]);
660 if (ctx
->Depth
.Mask
) {
661 /* Update Z buffer */
662 for (i
=0; i
<n
; i
++) {
664 zptr
= Z_ADDRESS(ctx
,x
[i
],y
[i
]);
670 /* Don't update Z buffer or mask */
674 /* depth test never passes */
680 gl_problem(ctx
, "Bad depth func in gl_depth_test_pixels_generic");
687 * glDepthFunc( GL_LESS ) and glDepthMask( GL_TRUE ).
689 void gl_depth_test_pixels_less( GLcontext
* ctx
,
690 GLuint n
, const GLint x
[], const GLint y
[],
691 const GLdepth z
[], GLubyte mask
[] )
696 for (i
=0; i
<n
; i
++) {
698 zptr
= Z_ADDRESS(ctx
,x
[i
],y
[i
]);
713 * glDepthFunc( GL_GREATER ) and glDepthMask( GL_TRUE ).
715 void gl_depth_test_pixels_greater( GLcontext
* ctx
,
716 GLuint n
, const GLint x
[], const GLint y
[],
717 const GLdepth z
[], GLubyte mask
[] )
722 for (i
=0; i
<n
; i
++) {
724 zptr
= Z_ADDRESS(ctx
,x
[i
],y
[i
]);
740 /**********************************************************************/
741 /***** Read Depth Buffer *****/
742 /**********************************************************************/
746 * Return a span of depth values from the depth buffer as floats in [0,1].
747 * This function is only called through Driver.read_depth_span_float()
748 * Input: n - how many pixels
749 * x,y - location of first pixel
750 * Output: depth - the array of depth values
752 void gl_read_depth_span_float( GLcontext
* ctx
,
753 GLuint n
, GLint x
, GLint y
, GLfloat depth
[] )
759 scale
= 1.0F
/ DEPTH_SCALE
;
761 if (ctx
->Buffer
->Depth
) {
762 zptr
= Z_ADDRESS( ctx
, x
, y
);
764 depth
[i
] = (GLfloat
) zptr
[i
] * scale
;
776 * Return a span of depth values from the depth buffer as integers in
778 * This function is only called through Driver.read_depth_span_int()
779 * Input: n - how many pixels
780 * x,y - location of first pixel
781 * Output: depth - the array of depth values
783 void gl_read_depth_span_int( GLcontext
* ctx
,
784 GLuint n
, GLint x
, GLint y
, GLdepth depth
[] )
786 if (ctx
->Buffer
->Depth
) {
787 GLdepth
*zptr
= Z_ADDRESS( ctx
, x
, y
);
788 MEMCPY( depth
, zptr
, n
* sizeof(GLdepth
) );
800 /**********************************************************************/
801 /***** Allocate and Clear Depth Buffer *****/
802 /**********************************************************************/
807 * Allocate a new depth buffer. If there's already a depth buffer allocated
808 * it will be free()'d. The new depth buffer will be uniniitalized.
809 * This function is only called through Driver.alloc_depth_buffer.
811 void gl_alloc_depth_buffer( GLcontext
* ctx
)
813 /* deallocate current depth buffer if present */
814 if (ctx
->Buffer
->Depth
) {
815 FREE(ctx
->Buffer
->Depth
);
816 ctx
->Buffer
->Depth
= NULL
;
819 /* allocate new depth buffer, but don't initialize it */
820 ctx
->Buffer
->Depth
= (GLdepth
*) MALLOC( ctx
->Buffer
->Width
821 * ctx
->Buffer
->Height
823 if (!ctx
->Buffer
->Depth
) {
825 ctx
->Depth
.Test
= GL_FALSE
;
826 ctx
->NewState
|= NEW_RASTER_OPS
;
827 gl_error( ctx
, GL_OUT_OF_MEMORY
, "Couldn't allocate depth buffer" );
835 * Clear the depth buffer. If the depth buffer doesn't exist yet we'll
837 * This function is only called through Driver.clear_depth_buffer.
839 void gl_clear_depth_buffer( GLcontext
* ctx
)
841 GLdepth clear_value
= (GLdepth
) (ctx
->Depth
.Clear
* DEPTH_SCALE
);
843 if (ctx
->Visual
->DepthBits
==0 || !ctx
->Buffer
->Depth
|| !ctx
->Depth
.Mask
) {
844 /* no depth buffer, or writing to it is disabled */
848 /* The loops in this function have been written so the IRIX 5.3
849 * C compiler can unroll them. Hopefully other compilers can too!
852 if (ctx
->Scissor
.Enabled
) {
853 /* only clear scissor region */
855 for (y
=ctx
->Buffer
->Ymin
; y
<=ctx
->Buffer
->Ymax
; y
++) {
856 GLdepth
*d
= Z_ADDRESS( ctx
, ctx
->Buffer
->Xmin
, y
);
857 GLint n
= ctx
->Buffer
->Xmax
- ctx
->Buffer
->Xmin
+ 1;
865 /* clear whole buffer */
866 if (sizeof(GLdepth
)==2 && (clear_value
&0xff)==(clear_value
>>8)) {
867 /* lower and upper bytes of clear_value are same, use MEMSET */
868 MEMSET( ctx
->Buffer
->Depth
, clear_value
&0xff,
869 2*ctx
->Buffer
->Width
*ctx
->Buffer
->Height
);
872 GLdepth
*d
= ctx
->Buffer
->Depth
;
873 GLint n
= ctx
->Buffer
->Width
* ctx
->Buffer
->Height
;
875 d
[0] = clear_value
; d
[1] = clear_value
;
876 d
[2] = clear_value
; d
[3] = clear_value
;
877 d
[4] = clear_value
; d
[5] = clear_value
;
878 d
[6] = clear_value
; d
[7] = clear_value
;
879 d
[8] = clear_value
; d
[9] = clear_value
;
880 d
[10] = clear_value
; d
[11] = clear_value
;
881 d
[12] = clear_value
; d
[13] = clear_value
;
882 d
[14] = clear_value
; d
[15] = clear_value
;