1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the "Software"), 8848b8605Smrg * to deal in the Software without restriction, including without limitation 9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 11848b8605Smrg * Software is furnished to do so, subject to the following conditions: 12848b8605Smrg * 13848b8605Smrg * The above copyright notice and this permission notice shall be included 14848b8605Smrg * in all copies or substantial portions of the Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg 26848b8605Smrg#include "main/glheader.h" 27848b8605Smrg#include "main/context.h" 28848b8605Smrg#include "main/formats.h" 29848b8605Smrg#include "main/format_unpack.h" 30848b8605Smrg#include "main/format_pack.h" 31848b8605Smrg#include "main/macros.h" 32848b8605Smrg#include "main/imports.h" 33848b8605Smrg 34848b8605Smrg#include "s_context.h" 35848b8605Smrg#include "s_depth.h" 36848b8605Smrg#include "s_span.h" 37848b8605Smrg 38848b8605Smrg 39848b8605Smrg 40848b8605Smrg#define Z_TEST(COMPARE) \ 41848b8605Smrg do { \ 42848b8605Smrg GLuint i; \ 43848b8605Smrg for (i = 0; i < n; i++) { \ 44848b8605Smrg if (mask[i]) { \ 45848b8605Smrg if (COMPARE) { \ 46848b8605Smrg /* pass */ \ 47848b8605Smrg if (write) { \ 48848b8605Smrg zbuffer[i] = zfrag[i]; \ 49848b8605Smrg } \ 50848b8605Smrg passed++; \ 51848b8605Smrg } \ 52848b8605Smrg else { \ 53848b8605Smrg /* fail */ \ 54848b8605Smrg mask[i] = 0; \ 55848b8605Smrg } \ 56848b8605Smrg } \ 57848b8605Smrg } \ 58848b8605Smrg } while (0) 59848b8605Smrg 60848b8605Smrg 61848b8605Smrg/** 62848b8605Smrg * Do depth test for an array of 16-bit Z values. 63848b8605Smrg * @param zbuffer array of Z buffer values (16-bit) 64848b8605Smrg * @param zfrag array of fragment Z values (use 16-bit in 32-bit uint) 65848b8605Smrg * @param mask which fragments are alive, killed afterward 66848b8605Smrg * @return number of fragments which pass the test. 67848b8605Smrg */ 68848b8605Smrgstatic GLuint 69848b8605Smrgdepth_test_span16( struct gl_context *ctx, GLuint n, 70848b8605Smrg GLushort zbuffer[], const GLuint zfrag[], GLubyte mask[] ) 71848b8605Smrg{ 72848b8605Smrg const GLboolean write = ctx->Depth.Mask; 73848b8605Smrg GLuint passed = 0; 74848b8605Smrg 75848b8605Smrg /* switch cases ordered from most frequent to less frequent */ 76848b8605Smrg switch (ctx->Depth.Func) { 77848b8605Smrg case GL_LESS: 78848b8605Smrg Z_TEST(zfrag[i] < zbuffer[i]); 79848b8605Smrg break; 80848b8605Smrg case GL_LEQUAL: 81848b8605Smrg Z_TEST(zfrag[i] <= zbuffer[i]); 82848b8605Smrg break; 83848b8605Smrg case GL_GEQUAL: 84848b8605Smrg Z_TEST(zfrag[i] >= zbuffer[i]); 85848b8605Smrg break; 86848b8605Smrg case GL_GREATER: 87848b8605Smrg Z_TEST(zfrag[i] > zbuffer[i]); 88848b8605Smrg break; 89848b8605Smrg case GL_NOTEQUAL: 90848b8605Smrg Z_TEST(zfrag[i] != zbuffer[i]); 91848b8605Smrg break; 92848b8605Smrg case GL_EQUAL: 93848b8605Smrg Z_TEST(zfrag[i] == zbuffer[i]); 94848b8605Smrg break; 95848b8605Smrg case GL_ALWAYS: 96848b8605Smrg Z_TEST(1); 97848b8605Smrg break; 98848b8605Smrg case GL_NEVER: 99848b8605Smrg memset(mask, 0, n * sizeof(GLubyte)); 100848b8605Smrg break; 101848b8605Smrg default: 102848b8605Smrg _mesa_problem(ctx, "Bad depth func in depth_test_span16"); 103848b8605Smrg } 104848b8605Smrg 105848b8605Smrg return passed; 106848b8605Smrg} 107848b8605Smrg 108848b8605Smrg 109848b8605Smrg/** 110848b8605Smrg * Do depth test for an array of 32-bit Z values. 111848b8605Smrg * @param zbuffer array of Z buffer values (32-bit) 112848b8605Smrg * @param zfrag array of fragment Z values (use 32-bits in 32-bit uint) 113848b8605Smrg * @param mask which fragments are alive, killed afterward 114848b8605Smrg * @return number of fragments which pass the test. 115848b8605Smrg */ 116848b8605Smrgstatic GLuint 117848b8605Smrgdepth_test_span32( struct gl_context *ctx, GLuint n, 118848b8605Smrg GLuint zbuffer[], const GLuint zfrag[], GLubyte mask[]) 119848b8605Smrg{ 120848b8605Smrg const GLboolean write = ctx->Depth.Mask; 121848b8605Smrg GLuint passed = 0; 122848b8605Smrg 123848b8605Smrg /* switch cases ordered from most frequent to less frequent */ 124848b8605Smrg switch (ctx->Depth.Func) { 125848b8605Smrg case GL_LESS: 126848b8605Smrg Z_TEST(zfrag[i] < zbuffer[i]); 127848b8605Smrg break; 128848b8605Smrg case GL_LEQUAL: 129848b8605Smrg Z_TEST(zfrag[i] <= zbuffer[i]); 130848b8605Smrg break; 131848b8605Smrg case GL_GEQUAL: 132848b8605Smrg Z_TEST(zfrag[i] >= zbuffer[i]); 133848b8605Smrg break; 134848b8605Smrg case GL_GREATER: 135848b8605Smrg Z_TEST(zfrag[i] > zbuffer[i]); 136848b8605Smrg break; 137848b8605Smrg case GL_NOTEQUAL: 138848b8605Smrg Z_TEST(zfrag[i] != zbuffer[i]); 139848b8605Smrg break; 140848b8605Smrg case GL_EQUAL: 141848b8605Smrg Z_TEST(zfrag[i] == zbuffer[i]); 142848b8605Smrg break; 143848b8605Smrg case GL_ALWAYS: 144848b8605Smrg Z_TEST(1); 145848b8605Smrg break; 146848b8605Smrg case GL_NEVER: 147848b8605Smrg memset(mask, 0, n * sizeof(GLubyte)); 148848b8605Smrg break; 149848b8605Smrg default: 150848b8605Smrg _mesa_problem(ctx, "Bad depth func in depth_test_span32"); 151848b8605Smrg } 152848b8605Smrg 153848b8605Smrg return passed; 154848b8605Smrg} 155848b8605Smrg 156848b8605Smrg 157848b8605Smrg/** 158848b8605Smrg * Clamp fragment Z values to the depth near/far range (glDepthRange()). 159848b8605Smrg * This is used when GL_ARB_depth_clamp/GL_DEPTH_CLAMP is turned on. 160848b8605Smrg * In that case, vertexes are not clipped against the near/far planes 161848b8605Smrg * so rasterization will produce fragment Z values outside the usual 162848b8605Smrg * [0,1] range. 163848b8605Smrg */ 164848b8605Smrgvoid 165848b8605Smrg_swrast_depth_clamp_span( struct gl_context *ctx, SWspan *span ) 166848b8605Smrg{ 167848b8605Smrg struct gl_framebuffer *fb = ctx->DrawBuffer; 168848b8605Smrg const GLuint count = span->end; 169848b8605Smrg GLint *zValues = (GLint *) span->array->z; /* sign change */ 170848b8605Smrg GLint min, max; 171848b8605Smrg GLfloat min_f, max_f; 172848b8605Smrg GLuint i; 173848b8605Smrg 174848b8605Smrg if (ctx->ViewportArray[0].Near < ctx->ViewportArray[0].Far) { 175848b8605Smrg min_f = ctx->ViewportArray[0].Near; 176848b8605Smrg max_f = ctx->ViewportArray[0].Far; 177848b8605Smrg } else { 178848b8605Smrg min_f = ctx->ViewportArray[0].Far; 179848b8605Smrg max_f = ctx->ViewportArray[0].Near; 180848b8605Smrg } 181848b8605Smrg 182848b8605Smrg /* Convert floating point values in [0,1] to device Z coordinates in 183848b8605Smrg * [0, DepthMax]. 184848b8605Smrg * ex: If the Z buffer has 24 bits, DepthMax = 0xffffff. 185848b8605Smrg * 186848b8605Smrg * XXX this all falls apart if we have 31 or more bits of Z because 187848b8605Smrg * the triangle rasterization code produces unsigned Z values. Negative 188848b8605Smrg * vertex Z values come out as large fragment Z uints. 189848b8605Smrg */ 190848b8605Smrg min = (GLint) (min_f * fb->_DepthMaxF); 191848b8605Smrg max = (GLint) (max_f * fb->_DepthMaxF); 192848b8605Smrg if (max < 0) 193848b8605Smrg max = 0x7fffffff; /* catch over flow for 30-bit z */ 194848b8605Smrg 195848b8605Smrg /* Note that we do the comparisons here using signed integers. 196848b8605Smrg */ 197848b8605Smrg for (i = 0; i < count; i++) { 198848b8605Smrg if (zValues[i] < min) 199848b8605Smrg zValues[i] = min; 200848b8605Smrg if (zValues[i] > max) 201848b8605Smrg zValues[i] = max; 202848b8605Smrg } 203848b8605Smrg} 204848b8605Smrg 205848b8605Smrg 206848b8605Smrg/** 207848b8605Smrg * Get array of 32-bit z values from the depth buffer. With clipping. 208848b8605Smrg * Note: the returned values are always in the range [0, 2^32-1]. 209848b8605Smrg */ 210848b8605Smrgstatic void 211848b8605Smrgget_z32_values(struct gl_context *ctx, struct gl_renderbuffer *rb, 212848b8605Smrg GLuint count, const GLint x[], const GLint y[], 213848b8605Smrg GLuint zbuffer[]) 214848b8605Smrg{ 215848b8605Smrg struct swrast_renderbuffer *srb = swrast_renderbuffer(rb); 216848b8605Smrg const GLint w = rb->Width, h = rb->Height; 217848b8605Smrg const GLubyte *map = _swrast_pixel_address(rb, 0, 0); 218848b8605Smrg GLuint i; 219848b8605Smrg 220848b8605Smrg if (rb->Format == MESA_FORMAT_Z_UNORM32) { 221848b8605Smrg const GLint rowStride = srb->RowStride; 222848b8605Smrg for (i = 0; i < count; i++) { 223848b8605Smrg if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { 224848b8605Smrg zbuffer[i] = *((GLuint *) (map + y[i] * rowStride + x[i] * 4)); 225848b8605Smrg } 226848b8605Smrg } 227848b8605Smrg } 228848b8605Smrg else { 229848b8605Smrg const GLint bpp = _mesa_get_format_bytes(rb->Format); 230848b8605Smrg const GLint rowStride = srb->RowStride; 231848b8605Smrg for (i = 0; i < count; i++) { 232848b8605Smrg if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { 233848b8605Smrg const GLubyte *src = map + y[i] * rowStride+ x[i] * bpp; 234848b8605Smrg _mesa_unpack_uint_z_row(rb->Format, 1, src, &zbuffer[i]); 235848b8605Smrg } 236848b8605Smrg } 237848b8605Smrg } 238848b8605Smrg} 239848b8605Smrg 240848b8605Smrg 241848b8605Smrg/** 242848b8605Smrg * Put an array of 32-bit z values into the depth buffer. 243848b8605Smrg * Note: the z values are always in the range [0, 2^32-1]. 244848b8605Smrg */ 245848b8605Smrgstatic void 246848b8605Smrgput_z32_values(struct gl_context *ctx, struct gl_renderbuffer *rb, 247848b8605Smrg GLuint count, const GLint x[], const GLint y[], 248848b8605Smrg const GLuint zvalues[], const GLubyte mask[]) 249848b8605Smrg{ 250848b8605Smrg struct swrast_renderbuffer *srb = swrast_renderbuffer(rb); 251848b8605Smrg const GLint w = rb->Width, h = rb->Height; 252848b8605Smrg GLubyte *map = _swrast_pixel_address(rb, 0, 0); 253848b8605Smrg GLuint i; 254848b8605Smrg 255848b8605Smrg if (rb->Format == MESA_FORMAT_Z_UNORM32) { 256848b8605Smrg const GLint rowStride = srb->RowStride; 257848b8605Smrg for (i = 0; i < count; i++) { 258848b8605Smrg if (mask[i] && x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { 259848b8605Smrg GLuint *dst = (GLuint *) (map + y[i] * rowStride + x[i] * 4); 260848b8605Smrg *dst = zvalues[i]; 261848b8605Smrg } 262848b8605Smrg } 263848b8605Smrg } 264848b8605Smrg else { 265848b8605Smrg gl_pack_uint_z_func packZ = _mesa_get_pack_uint_z_func(rb->Format); 266848b8605Smrg const GLint bpp = _mesa_get_format_bytes(rb->Format); 267848b8605Smrg const GLint rowStride = srb->RowStride; 268848b8605Smrg for (i = 0; i < count; i++) { 269848b8605Smrg if (mask[i] && x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { 270848b8605Smrg void *dst = map + y[i] * rowStride + x[i] * bpp; 271848b8605Smrg packZ(zvalues + i, dst); 272848b8605Smrg } 273848b8605Smrg } 274848b8605Smrg } 275848b8605Smrg} 276848b8605Smrg 277848b8605Smrg 278848b8605Smrg/** 279848b8605Smrg * Apply depth (Z) buffer testing to the span. 280848b8605Smrg * \return approx number of pixels that passed (only zero is reliable) 281848b8605Smrg */ 282848b8605SmrgGLuint 283848b8605Smrg_swrast_depth_test_span(struct gl_context *ctx, SWspan *span) 284848b8605Smrg{ 285848b8605Smrg struct gl_framebuffer *fb = ctx->DrawBuffer; 286848b8605Smrg struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; 287848b8605Smrg const GLint bpp = _mesa_get_format_bytes(rb->Format); 288848b8605Smrg void *zStart; 289848b8605Smrg const GLuint count = span->end; 290848b8605Smrg const GLuint *fragZ = span->array->z; 291848b8605Smrg GLubyte *mask = span->array->mask; 292848b8605Smrg void *zBufferVals; 293848b8605Smrg GLuint *zBufferTemp = NULL; 294848b8605Smrg GLuint passed; 295848b8605Smrg GLuint zBits = _mesa_get_format_bits(rb->Format, GL_DEPTH_BITS); 296848b8605Smrg GLboolean ztest16 = GL_FALSE; 297848b8605Smrg 298848b8605Smrg if (span->arrayMask & SPAN_XY) 299848b8605Smrg zStart = NULL; 300848b8605Smrg else 301848b8605Smrg zStart = _swrast_pixel_address(rb, span->x, span->y); 302848b8605Smrg 303848b8605Smrg if (rb->Format == MESA_FORMAT_Z_UNORM16 && !(span->arrayMask & SPAN_XY)) { 304848b8605Smrg /* directly read/write row of 16-bit Z values */ 305848b8605Smrg zBufferVals = zStart; 306848b8605Smrg ztest16 = GL_TRUE; 307848b8605Smrg } 308848b8605Smrg else if (rb->Format == MESA_FORMAT_Z_UNORM32 && !(span->arrayMask & SPAN_XY)) { 309848b8605Smrg /* directly read/write row of 32-bit Z values */ 310848b8605Smrg zBufferVals = zStart; 311848b8605Smrg } 312848b8605Smrg else { 313848b8605Smrg /* copy Z buffer values into temp buffer (32-bit Z values) */ 314848b8605Smrg zBufferTemp = malloc(count * sizeof(GLuint)); 315848b8605Smrg if (!zBufferTemp) 316848b8605Smrg return 0; 317848b8605Smrg 318848b8605Smrg if (span->arrayMask & SPAN_XY) { 319848b8605Smrg get_z32_values(ctx, rb, count, 320848b8605Smrg span->array->x, span->array->y, zBufferTemp); 321848b8605Smrg } 322848b8605Smrg else { 323848b8605Smrg _mesa_unpack_uint_z_row(rb->Format, count, zStart, zBufferTemp); 324848b8605Smrg } 325848b8605Smrg 326848b8605Smrg if (zBits == 24) { 327848b8605Smrg GLuint i; 328848b8605Smrg /* Convert depth buffer values from 32 to 24 bits to match the 329848b8605Smrg * fragment Z values generated by rasterization. 330848b8605Smrg */ 331848b8605Smrg for (i = 0; i < count; i++) { 332848b8605Smrg zBufferTemp[i] >>= 8; 333848b8605Smrg } 334848b8605Smrg } 335848b8605Smrg else if (zBits == 16) { 336848b8605Smrg GLuint i; 337848b8605Smrg /* Convert depth buffer values from 32 to 16 bits */ 338848b8605Smrg for (i = 0; i < count; i++) { 339848b8605Smrg zBufferTemp[i] >>= 16; 340848b8605Smrg } 341848b8605Smrg } 342848b8605Smrg else { 343848b8605Smrg assert(zBits == 32); 344848b8605Smrg } 345848b8605Smrg 346848b8605Smrg zBufferVals = zBufferTemp; 347848b8605Smrg } 348848b8605Smrg 349848b8605Smrg /* do the depth test either with 16 or 32-bit values */ 350848b8605Smrg if (ztest16) 351848b8605Smrg passed = depth_test_span16(ctx, count, zBufferVals, fragZ, mask); 352848b8605Smrg else 353848b8605Smrg passed = depth_test_span32(ctx, count, zBufferVals, fragZ, mask); 354848b8605Smrg 355848b8605Smrg if (zBufferTemp) { 356848b8605Smrg /* need to write temp Z values back into the buffer */ 357848b8605Smrg 358848b8605Smrg /* Convert depth buffer values back to 32-bit values. The least 359848b8605Smrg * significant bits don't matter since they'll get dropped when 360848b8605Smrg * they're packed back into the depth buffer. 361848b8605Smrg */ 362848b8605Smrg if (zBits == 24) { 363848b8605Smrg GLuint i; 364848b8605Smrg for (i = 0; i < count; i++) { 365848b8605Smrg zBufferTemp[i] = (zBufferTemp[i] << 8); 366848b8605Smrg } 367848b8605Smrg } 368848b8605Smrg else if (zBits == 16) { 369848b8605Smrg GLuint i; 370848b8605Smrg for (i = 0; i < count; i++) { 371848b8605Smrg zBufferTemp[i] = zBufferTemp[i] << 16; 372848b8605Smrg } 373848b8605Smrg } 374848b8605Smrg 375848b8605Smrg if (span->arrayMask & SPAN_XY) { 376848b8605Smrg /* random locations */ 377848b8605Smrg put_z32_values(ctx, rb, count, span->array->x, span->array->y, 378848b8605Smrg zBufferTemp, mask); 379848b8605Smrg } 380848b8605Smrg else { 381848b8605Smrg /* horizontal row */ 382848b8605Smrg gl_pack_uint_z_func packZ = _mesa_get_pack_uint_z_func(rb->Format); 383848b8605Smrg GLubyte *dst = zStart; 384848b8605Smrg GLuint i; 385848b8605Smrg for (i = 0; i < count; i++) { 386848b8605Smrg if (mask[i]) { 387848b8605Smrg packZ(&zBufferTemp[i], dst); 388848b8605Smrg } 389848b8605Smrg dst += bpp; 390848b8605Smrg } 391848b8605Smrg } 392848b8605Smrg 393848b8605Smrg free(zBufferTemp); 394848b8605Smrg } 395848b8605Smrg 396848b8605Smrg if (passed < count) { 397848b8605Smrg span->writeAll = GL_FALSE; 398848b8605Smrg } 399848b8605Smrg return passed; 400848b8605Smrg} 401848b8605Smrg 402848b8605Smrg 403848b8605Smrg/** 404848b8605Smrg * GL_EXT_depth_bounds_test extension. 405848b8605Smrg * Discard fragments depending on whether the corresponding Z-buffer 406848b8605Smrg * values are outside the depth bounds test range. 407848b8605Smrg * Note: we test the Z buffer values, not the fragment Z values! 408848b8605Smrg * \return GL_TRUE if any fragments pass, GL_FALSE if no fragments pass 409848b8605Smrg */ 410848b8605SmrgGLboolean 411848b8605Smrg_swrast_depth_bounds_test( struct gl_context *ctx, SWspan *span ) 412848b8605Smrg{ 413848b8605Smrg struct gl_framebuffer *fb = ctx->DrawBuffer; 414848b8605Smrg struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; 415848b8605Smrg GLubyte *zStart; 416b8e80941Smrg GLuint zMin = (GLuint)((double)ctx->Depth.BoundsMin * 0xffffffff); 417b8e80941Smrg GLuint zMax = (GLuint)((double)ctx->Depth.BoundsMax * 0xffffffff); 418848b8605Smrg GLubyte *mask = span->array->mask; 419848b8605Smrg const GLuint count = span->end; 420848b8605Smrg GLuint i; 421848b8605Smrg GLboolean anyPass = GL_FALSE; 422848b8605Smrg GLuint *zBufferTemp; 423848b8605Smrg const GLuint *zBufferVals; 424848b8605Smrg 425848b8605Smrg zBufferTemp = malloc(count * sizeof(GLuint)); 426848b8605Smrg if (!zBufferTemp) { 427848b8605Smrg /* don't generate a stream of OUT_OF_MEMORY errors here */ 428848b8605Smrg return GL_FALSE; 429848b8605Smrg } 430848b8605Smrg 431848b8605Smrg if (span->arrayMask & SPAN_XY) 432848b8605Smrg zStart = NULL; 433848b8605Smrg else 434848b8605Smrg zStart = _swrast_pixel_address(rb, span->x, span->y); 435848b8605Smrg 436848b8605Smrg if (rb->Format == MESA_FORMAT_Z_UNORM32 && !(span->arrayMask & SPAN_XY)) { 437848b8605Smrg /* directly access 32-bit values in the depth buffer */ 438848b8605Smrg zBufferVals = (const GLuint *) zStart; 439848b8605Smrg } 440848b8605Smrg else { 441b8e80941Smrg /* Round the bounds to the precision of the zbuffer. */ 442b8e80941Smrg if (rb->Format == MESA_FORMAT_Z_UNORM16) { 443b8e80941Smrg zMin = (zMin & 0xffff0000) | (zMin >> 16); 444b8e80941Smrg zMax = (zMax & 0xffff0000) | (zMax >> 16); 445b8e80941Smrg } else { 446b8e80941Smrg /* 24 bits */ 447b8e80941Smrg zMin = (zMin & 0xffffff00) | (zMin >> 24); 448b8e80941Smrg zMax = (zMax & 0xffffff00) | (zMax >> 24); 449b8e80941Smrg } 450b8e80941Smrg 451848b8605Smrg /* unpack Z values into a temporary array */ 452848b8605Smrg if (span->arrayMask & SPAN_XY) { 453848b8605Smrg get_z32_values(ctx, rb, count, span->array->x, span->array->y, 454848b8605Smrg zBufferTemp); 455848b8605Smrg } 456848b8605Smrg else { 457848b8605Smrg _mesa_unpack_uint_z_row(rb->Format, count, zStart, zBufferTemp); 458848b8605Smrg } 459848b8605Smrg zBufferVals = zBufferTemp; 460848b8605Smrg } 461848b8605Smrg 462848b8605Smrg /* Now do the tests */ 463848b8605Smrg for (i = 0; i < count; i++) { 464848b8605Smrg if (mask[i]) { 465848b8605Smrg if (zBufferVals[i] < zMin || zBufferVals[i] > zMax) 466848b8605Smrg mask[i] = GL_FALSE; 467848b8605Smrg else 468848b8605Smrg anyPass = GL_TRUE; 469848b8605Smrg } 470848b8605Smrg } 471848b8605Smrg 472848b8605Smrg free(zBufferTemp); 473848b8605Smrg 474848b8605Smrg return anyPass; 475848b8605Smrg} 476848b8605Smrg 477848b8605Smrg 478848b8605Smrg 479848b8605Smrg/**********************************************************************/ 480848b8605Smrg/***** Read Depth Buffer *****/ 481848b8605Smrg/**********************************************************************/ 482848b8605Smrg 483848b8605Smrg 484848b8605Smrg/** 485848b8605Smrg * Read a span of depth values from the given depth renderbuffer, returning 486848b8605Smrg * the values as GLfloats. 487848b8605Smrg * This function does clipping to prevent reading outside the depth buffer's 488848b8605Smrg * bounds. 489848b8605Smrg */ 490848b8605Smrgvoid 491848b8605Smrg_swrast_read_depth_span_float(struct gl_context *ctx, 492848b8605Smrg struct gl_renderbuffer *rb, 493848b8605Smrg GLint n, GLint x, GLint y, GLfloat depth[]) 494848b8605Smrg{ 495848b8605Smrg if (!rb) { 496848b8605Smrg /* really only doing this to prevent FP exceptions later */ 497848b8605Smrg memset(depth, 0, n * sizeof(GLfloat)); 498848b8605Smrg return; 499848b8605Smrg } 500848b8605Smrg 501848b8605Smrg if (y < 0 || y >= (GLint) rb->Height || 502848b8605Smrg x + n <= 0 || x >= (GLint) rb->Width) { 503848b8605Smrg /* span is completely outside framebuffer */ 504848b8605Smrg memset(depth, 0, n * sizeof(GLfloat)); 505848b8605Smrg return; 506848b8605Smrg } 507848b8605Smrg 508848b8605Smrg if (x < 0) { 509848b8605Smrg GLint dx = -x; 510848b8605Smrg GLint i; 511848b8605Smrg for (i = 0; i < dx; i++) 512848b8605Smrg depth[i] = 0.0; 513848b8605Smrg x = 0; 514848b8605Smrg n -= dx; 515848b8605Smrg depth += dx; 516848b8605Smrg } 517848b8605Smrg if (x + n > (GLint) rb->Width) { 518848b8605Smrg GLint dx = x + n - (GLint) rb->Width; 519848b8605Smrg GLint i; 520848b8605Smrg for (i = 0; i < dx; i++) 521848b8605Smrg depth[n - i - 1] = 0.0; 522848b8605Smrg n -= dx; 523848b8605Smrg } 524848b8605Smrg if (n <= 0) { 525848b8605Smrg return; 526848b8605Smrg } 527848b8605Smrg 528848b8605Smrg _mesa_unpack_float_z_row(rb->Format, n, _swrast_pixel_address(rb, x, y), 529848b8605Smrg depth); 530848b8605Smrg} 531848b8605Smrg 532848b8605Smrg 533848b8605Smrg/** 534848b8605Smrg * Clear the given z/depth renderbuffer. If the buffer is a combined 535848b8605Smrg * depth+stencil buffer, only the Z bits will be touched. 536848b8605Smrg */ 537848b8605Smrgvoid 538848b8605Smrg_swrast_clear_depth_buffer(struct gl_context *ctx) 539848b8605Smrg{ 540848b8605Smrg struct gl_renderbuffer *rb = 541848b8605Smrg ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 542848b8605Smrg GLint x, y, width, height; 543848b8605Smrg GLubyte *map; 544848b8605Smrg GLint rowStride, i, j; 545848b8605Smrg GLbitfield mapMode; 546848b8605Smrg 547848b8605Smrg if (!rb || !ctx->Depth.Mask) { 548848b8605Smrg /* no depth buffer, or writing to it is disabled */ 549848b8605Smrg return; 550848b8605Smrg } 551848b8605Smrg 552848b8605Smrg /* compute region to clear */ 553848b8605Smrg x = ctx->DrawBuffer->_Xmin; 554848b8605Smrg y = ctx->DrawBuffer->_Ymin; 555848b8605Smrg width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; 556848b8605Smrg height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; 557848b8605Smrg 558848b8605Smrg mapMode = GL_MAP_WRITE_BIT; 559848b8605Smrg if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || 560848b8605Smrg rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT || 561848b8605Smrg rb->Format == MESA_FORMAT_S8_UINT_Z24_UNORM || 562848b8605Smrg rb->Format == MESA_FORMAT_X8_UINT_Z24_UNORM) { 563848b8605Smrg mapMode |= GL_MAP_READ_BIT; 564848b8605Smrg } 565848b8605Smrg 566848b8605Smrg ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, 567b8e80941Smrg mapMode, &map, &rowStride, 568b8e80941Smrg ctx->DrawBuffer->FlipY); 569848b8605Smrg if (!map) { 570848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(depth)"); 571848b8605Smrg return; 572848b8605Smrg } 573848b8605Smrg 574848b8605Smrg switch (rb->Format) { 575848b8605Smrg case MESA_FORMAT_Z_UNORM16: 576848b8605Smrg { 577848b8605Smrg GLfloat clear = (GLfloat) ctx->Depth.Clear; 578848b8605Smrg GLushort clearVal = 0; 579848b8605Smrg _mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal); 580848b8605Smrg if (clearVal == 0xffff && width * 2 == rowStride) { 581848b8605Smrg /* common case */ 582848b8605Smrg memset(map, 0xff, width * height * 2); 583848b8605Smrg } 584848b8605Smrg else { 585848b8605Smrg for (i = 0; i < height; i++) { 586848b8605Smrg GLushort *row = (GLushort *) map; 587848b8605Smrg for (j = 0; j < width; j++) { 588848b8605Smrg row[j] = clearVal; 589848b8605Smrg } 590848b8605Smrg map += rowStride; 591848b8605Smrg } 592848b8605Smrg } 593848b8605Smrg } 594848b8605Smrg break; 595848b8605Smrg case MESA_FORMAT_Z_UNORM32: 596848b8605Smrg case MESA_FORMAT_Z_FLOAT32: 597848b8605Smrg { 598848b8605Smrg GLfloat clear = (GLfloat) ctx->Depth.Clear; 599848b8605Smrg GLuint clearVal = 0; 600848b8605Smrg _mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal); 601848b8605Smrg for (i = 0; i < height; i++) { 602848b8605Smrg GLuint *row = (GLuint *) map; 603848b8605Smrg for (j = 0; j < width; j++) { 604848b8605Smrg row[j] = clearVal; 605848b8605Smrg } 606848b8605Smrg map += rowStride; 607848b8605Smrg } 608848b8605Smrg } 609848b8605Smrg break; 610848b8605Smrg case MESA_FORMAT_Z24_UNORM_S8_UINT: 611848b8605Smrg case MESA_FORMAT_Z24_UNORM_X8_UINT: 612848b8605Smrg case MESA_FORMAT_S8_UINT_Z24_UNORM: 613848b8605Smrg case MESA_FORMAT_X8_UINT_Z24_UNORM: 614848b8605Smrg { 615848b8605Smrg GLfloat clear = (GLfloat) ctx->Depth.Clear; 616848b8605Smrg GLuint clearVal = 0; 617848b8605Smrg GLuint mask; 618848b8605Smrg 619848b8605Smrg if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || 620848b8605Smrg rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT) 621848b8605Smrg mask = 0xff000000; 622848b8605Smrg else 623848b8605Smrg mask = 0xff; 624848b8605Smrg 625848b8605Smrg _mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal); 626848b8605Smrg for (i = 0; i < height; i++) { 627848b8605Smrg GLuint *row = (GLuint *) map; 628848b8605Smrg for (j = 0; j < width; j++) { 629848b8605Smrg row[j] = (row[j] & mask) | clearVal; 630848b8605Smrg } 631848b8605Smrg map += rowStride; 632848b8605Smrg } 633848b8605Smrg 634848b8605Smrg } 635848b8605Smrg break; 636848b8605Smrg case MESA_FORMAT_Z32_FLOAT_S8X24_UINT: 637848b8605Smrg /* XXX untested */ 638848b8605Smrg { 639848b8605Smrg GLfloat clearVal = (GLfloat) ctx->Depth.Clear; 640848b8605Smrg for (i = 0; i < height; i++) { 641848b8605Smrg GLfloat *row = (GLfloat *) map; 642848b8605Smrg for (j = 0; j < width; j++) { 643848b8605Smrg row[j * 2] = clearVal; 644848b8605Smrg } 645848b8605Smrg map += rowStride; 646848b8605Smrg } 647848b8605Smrg } 648848b8605Smrg break; 649848b8605Smrg default: 650848b8605Smrg _mesa_problem(ctx, "Unexpected depth buffer format %s" 651848b8605Smrg " in _swrast_clear_depth_buffer()", 652848b8605Smrg _mesa_get_format_name(rb->Format)); 653848b8605Smrg } 654848b8605Smrg 655848b8605Smrg ctx->Driver.UnmapRenderbuffer(ctx, rb); 656848b8605Smrg} 657848b8605Smrg 658848b8605Smrg 659848b8605Smrg 660848b8605Smrg 661848b8605Smrg/** 662848b8605Smrg * Clear both depth and stencil values in a combined depth+stencil buffer. 663848b8605Smrg */ 664848b8605Smrgvoid 665848b8605Smrg_swrast_clear_depth_stencil_buffer(struct gl_context *ctx) 666848b8605Smrg{ 667848b8605Smrg const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits; 668848b8605Smrg const GLuint writeMask = ctx->Stencil.WriteMask[0]; 669848b8605Smrg const GLuint stencilMax = (1 << stencilBits) - 1; 670848b8605Smrg struct gl_renderbuffer *rb = 671848b8605Smrg ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 672848b8605Smrg GLint x, y, width, height; 673848b8605Smrg GLbitfield mapMode; 674848b8605Smrg GLubyte *map; 675848b8605Smrg GLint rowStride, i, j; 676848b8605Smrg 677848b8605Smrg /* check that we really have a combined depth+stencil buffer */ 678848b8605Smrg assert(rb == ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer); 679848b8605Smrg 680848b8605Smrg /* compute region to clear */ 681848b8605Smrg x = ctx->DrawBuffer->_Xmin; 682848b8605Smrg y = ctx->DrawBuffer->_Ymin; 683848b8605Smrg width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; 684848b8605Smrg height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; 685848b8605Smrg 686848b8605Smrg mapMode = GL_MAP_WRITE_BIT; 687848b8605Smrg if ((writeMask & stencilMax) != stencilMax) { 688848b8605Smrg /* need to mask stencil values */ 689848b8605Smrg mapMode |= GL_MAP_READ_BIT; 690848b8605Smrg } 691848b8605Smrg 692848b8605Smrg ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, 693b8e80941Smrg mapMode, &map, &rowStride, 694b8e80941Smrg ctx->DrawBuffer->FlipY); 695848b8605Smrg if (!map) { 696848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(depth+stencil)"); 697848b8605Smrg return; 698848b8605Smrg } 699848b8605Smrg 700848b8605Smrg switch (rb->Format) { 701848b8605Smrg case MESA_FORMAT_Z24_UNORM_S8_UINT: 702848b8605Smrg case MESA_FORMAT_S8_UINT_Z24_UNORM: 703848b8605Smrg { 704848b8605Smrg GLfloat zClear = (GLfloat) ctx->Depth.Clear; 705848b8605Smrg GLuint clear = 0, mask; 706848b8605Smrg 707848b8605Smrg _mesa_pack_float_z_row(rb->Format, 1, &zClear, &clear); 708848b8605Smrg 709848b8605Smrg if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT) { 710848b8605Smrg mask = ((~writeMask) & 0xff) << 24; 711848b8605Smrg clear |= (ctx->Stencil.Clear & writeMask & 0xff) << 24; 712848b8605Smrg } 713848b8605Smrg else { 714848b8605Smrg mask = ((~writeMask) & 0xff); 715848b8605Smrg clear |= (ctx->Stencil.Clear & writeMask & 0xff); 716848b8605Smrg } 717848b8605Smrg 718848b8605Smrg for (i = 0; i < height; i++) { 719848b8605Smrg GLuint *row = (GLuint *) map; 720848b8605Smrg if (mask != 0x0) { 721848b8605Smrg for (j = 0; j < width; j++) { 722848b8605Smrg row[j] = (row[j] & mask) | clear; 723848b8605Smrg } 724848b8605Smrg } 725848b8605Smrg else { 726848b8605Smrg for (j = 0; j < width; j++) { 727848b8605Smrg row[j] = clear; 728848b8605Smrg } 729848b8605Smrg } 730848b8605Smrg map += rowStride; 731848b8605Smrg } 732848b8605Smrg } 733848b8605Smrg break; 734848b8605Smrg case MESA_FORMAT_Z32_FLOAT_S8X24_UINT: 735848b8605Smrg /* XXX untested */ 736848b8605Smrg { 737848b8605Smrg const GLfloat zClear = (GLfloat) ctx->Depth.Clear; 738848b8605Smrg const GLuint sClear = ctx->Stencil.Clear & writeMask; 739848b8605Smrg const GLuint sMask = (~writeMask) & 0xff; 740848b8605Smrg for (i = 0; i < height; i++) { 741848b8605Smrg GLfloat *zRow = (GLfloat *) map; 742848b8605Smrg GLuint *sRow = (GLuint *) map; 743848b8605Smrg for (j = 0; j < width; j++) { 744848b8605Smrg zRow[j * 2 + 0] = zClear; 745848b8605Smrg } 746848b8605Smrg if (sMask != 0) { 747848b8605Smrg for (j = 0; j < width; j++) { 748848b8605Smrg sRow[j * 2 + 1] = (sRow[j * 2 + 1] & sMask) | sClear; 749848b8605Smrg } 750848b8605Smrg } 751848b8605Smrg else { 752848b8605Smrg for (j = 0; j < width; j++) { 753848b8605Smrg sRow[j * 2 + 1] = sClear; 754848b8605Smrg } 755848b8605Smrg } 756848b8605Smrg map += rowStride; 757848b8605Smrg } 758848b8605Smrg } 759848b8605Smrg break; 760848b8605Smrg default: 761848b8605Smrg _mesa_problem(ctx, "Unexpected depth buffer format %s" 762848b8605Smrg " in _swrast_clear_depth_buffer()", 763848b8605Smrg _mesa_get_format_name(rb->Format)); 764848b8605Smrg } 765848b8605Smrg 766848b8605Smrg ctx->Driver.UnmapRenderbuffer(ctx, rb); 767848b8605Smrg 768848b8605Smrg} 769