17117f1b4Smrg/* 27117f1b4Smrg * Mesa 3-D graphics library 37117f1b4Smrg * 4c1f859d4Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 57117f1b4Smrg * 67117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a 77117f1b4Smrg * copy of this software and associated documentation files (the "Software"), 87117f1b4Smrg * to deal in the Software without restriction, including without limitation 97117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 107117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the 117117f1b4Smrg * Software is furnished to do so, subject to the following conditions: 127117f1b4Smrg * 137117f1b4Smrg * The above copyright notice and this permission notice shall be included 147117f1b4Smrg * in all copies or substantial portions of the Software. 157117f1b4Smrg * 167117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 177117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 187117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 237117f1b4Smrg */ 247117f1b4Smrg 257117f1b4Smrg 26c1f859d4Smrg#include "main/glheader.h" 27c1f859d4Smrg#include "main/context.h" 284a49301eSmrg#include "main/formats.h" 29af69d88dSmrg#include "main/format_unpack.h" 30af69d88dSmrg#include "main/format_pack.h" 31c1f859d4Smrg#include "main/macros.h" 327ec681f3Smrg 337117f1b4Smrg 34af69d88dSmrg#include "s_context.h" 357117f1b4Smrg#include "s_depth.h" 367117f1b4Smrg#include "s_span.h" 377117f1b4Smrg 387117f1b4Smrg 39af69d88dSmrg 40af69d88dSmrg#define Z_TEST(COMPARE) \ 41af69d88dSmrg do { \ 42af69d88dSmrg GLuint i; \ 43af69d88dSmrg for (i = 0; i < n; i++) { \ 44af69d88dSmrg if (mask[i]) { \ 45af69d88dSmrg if (COMPARE) { \ 46af69d88dSmrg /* pass */ \ 47af69d88dSmrg if (write) { \ 48af69d88dSmrg zbuffer[i] = zfrag[i]; \ 49af69d88dSmrg } \ 50af69d88dSmrg passed++; \ 51af69d88dSmrg } \ 52af69d88dSmrg else { \ 53af69d88dSmrg /* fail */ \ 54af69d88dSmrg mask[i] = 0; \ 55af69d88dSmrg } \ 56af69d88dSmrg } \ 57af69d88dSmrg } \ 58af69d88dSmrg } while (0) 59af69d88dSmrg 60af69d88dSmrg 617117f1b4Smrg/** 62af69d88dSmrg * Do depth test for an array of 16-bit Z values. 63af69d88dSmrg * @param zbuffer array of Z buffer values (16-bit) 64af69d88dSmrg * @param zfrag array of fragment Z values (use 16-bit in 32-bit uint) 65af69d88dSmrg * @param mask which fragments are alive, killed afterward 66af69d88dSmrg * @return number of fragments which pass the test. 677117f1b4Smrg */ 687117f1b4Smrgstatic GLuint 693464ebd5Sriastradhdepth_test_span16( struct gl_context *ctx, GLuint n, 70af69d88dSmrg GLushort zbuffer[], const GLuint zfrag[], GLubyte mask[] ) 717117f1b4Smrg{ 72af69d88dSmrg const GLboolean write = ctx->Depth.Mask; 737117f1b4Smrg GLuint passed = 0; 747117f1b4Smrg 757117f1b4Smrg /* switch cases ordered from most frequent to less frequent */ 767117f1b4Smrg switch (ctx->Depth.Func) { 77af69d88dSmrg case GL_LESS: 78af69d88dSmrg Z_TEST(zfrag[i] < zbuffer[i]); 79af69d88dSmrg break; 80af69d88dSmrg case GL_LEQUAL: 81af69d88dSmrg Z_TEST(zfrag[i] <= zbuffer[i]); 82af69d88dSmrg break; 83af69d88dSmrg case GL_GEQUAL: 84af69d88dSmrg Z_TEST(zfrag[i] >= zbuffer[i]); 85af69d88dSmrg break; 86af69d88dSmrg case GL_GREATER: 87af69d88dSmrg Z_TEST(zfrag[i] > zbuffer[i]); 88af69d88dSmrg break; 89af69d88dSmrg case GL_NOTEQUAL: 90af69d88dSmrg Z_TEST(zfrag[i] != zbuffer[i]); 91af69d88dSmrg break; 92af69d88dSmrg case GL_EQUAL: 93af69d88dSmrg Z_TEST(zfrag[i] == zbuffer[i]); 94af69d88dSmrg break; 95af69d88dSmrg case GL_ALWAYS: 96af69d88dSmrg Z_TEST(1); 97af69d88dSmrg break; 98af69d88dSmrg case GL_NEVER: 99af69d88dSmrg memset(mask, 0, n * sizeof(GLubyte)); 100af69d88dSmrg break; 101af69d88dSmrg default: 102af69d88dSmrg _mesa_problem(ctx, "Bad depth func in depth_test_span16"); 1037117f1b4Smrg } 1047117f1b4Smrg 1057117f1b4Smrg return passed; 1067117f1b4Smrg} 1077117f1b4Smrg 1087117f1b4Smrg 109af69d88dSmrg/** 110af69d88dSmrg * Do depth test for an array of 32-bit Z values. 111af69d88dSmrg * @param zbuffer array of Z buffer values (32-bit) 112af69d88dSmrg * @param zfrag array of fragment Z values (use 32-bits in 32-bit uint) 113af69d88dSmrg * @param mask which fragments are alive, killed afterward 114af69d88dSmrg * @return number of fragments which pass the test. 115af69d88dSmrg */ 1167117f1b4Smrgstatic GLuint 1173464ebd5Sriastradhdepth_test_span32( struct gl_context *ctx, GLuint n, 118af69d88dSmrg GLuint zbuffer[], const GLuint zfrag[], GLubyte mask[]) 1197117f1b4Smrg{ 120af69d88dSmrg const GLboolean write = ctx->Depth.Mask; 1217117f1b4Smrg GLuint passed = 0; 1227117f1b4Smrg 1237117f1b4Smrg /* switch cases ordered from most frequent to less frequent */ 1247117f1b4Smrg switch (ctx->Depth.Func) { 125af69d88dSmrg case GL_LESS: 126af69d88dSmrg Z_TEST(zfrag[i] < zbuffer[i]); 127af69d88dSmrg break; 128af69d88dSmrg case GL_LEQUAL: 129af69d88dSmrg Z_TEST(zfrag[i] <= zbuffer[i]); 130af69d88dSmrg break; 131af69d88dSmrg case GL_GEQUAL: 132af69d88dSmrg Z_TEST(zfrag[i] >= zbuffer[i]); 133af69d88dSmrg break; 134af69d88dSmrg case GL_GREATER: 135af69d88dSmrg Z_TEST(zfrag[i] > zbuffer[i]); 136af69d88dSmrg break; 137af69d88dSmrg case GL_NOTEQUAL: 138af69d88dSmrg Z_TEST(zfrag[i] != zbuffer[i]); 139af69d88dSmrg break; 140af69d88dSmrg case GL_EQUAL: 141af69d88dSmrg Z_TEST(zfrag[i] == zbuffer[i]); 142af69d88dSmrg break; 143af69d88dSmrg case GL_ALWAYS: 144af69d88dSmrg Z_TEST(1); 145af69d88dSmrg break; 146af69d88dSmrg case GL_NEVER: 147af69d88dSmrg memset(mask, 0, n * sizeof(GLubyte)); 148af69d88dSmrg break; 149af69d88dSmrg default: 150af69d88dSmrg _mesa_problem(ctx, "Bad depth func in depth_test_span32"); 1517117f1b4Smrg } 1527117f1b4Smrg 1537117f1b4Smrg return passed; 1547117f1b4Smrg} 1557117f1b4Smrg 1567117f1b4Smrg 1574a49301eSmrg/** 1584a49301eSmrg * Clamp fragment Z values to the depth near/far range (glDepthRange()). 1594a49301eSmrg * This is used when GL_ARB_depth_clamp/GL_DEPTH_CLAMP is turned on. 1604a49301eSmrg * In that case, vertexes are not clipped against the near/far planes 1614a49301eSmrg * so rasterization will produce fragment Z values outside the usual 1624a49301eSmrg * [0,1] range. 1634a49301eSmrg */ 1644a49301eSmrgvoid 1653464ebd5Sriastradh_swrast_depth_clamp_span( struct gl_context *ctx, SWspan *span ) 1664a49301eSmrg{ 1674a49301eSmrg struct gl_framebuffer *fb = ctx->DrawBuffer; 1684a49301eSmrg const GLuint count = span->end; 1694a49301eSmrg GLint *zValues = (GLint *) span->array->z; /* sign change */ 1704a49301eSmrg GLint min, max; 1714a49301eSmrg GLfloat min_f, max_f; 1724a49301eSmrg GLuint i; 1734a49301eSmrg 174af69d88dSmrg if (ctx->ViewportArray[0].Near < ctx->ViewportArray[0].Far) { 175af69d88dSmrg min_f = ctx->ViewportArray[0].Near; 176af69d88dSmrg max_f = ctx->ViewportArray[0].Far; 1774a49301eSmrg } else { 178af69d88dSmrg min_f = ctx->ViewportArray[0].Far; 179af69d88dSmrg max_f = ctx->ViewportArray[0].Near; 1804a49301eSmrg } 1814a49301eSmrg 1824a49301eSmrg /* Convert floating point values in [0,1] to device Z coordinates in 1834a49301eSmrg * [0, DepthMax]. 184cdc920a0Smrg * ex: If the Z buffer has 24 bits, DepthMax = 0xffffff. 1857ec681f3Smrg * 1864a49301eSmrg * XXX this all falls apart if we have 31 or more bits of Z because 1874a49301eSmrg * the triangle rasterization code produces unsigned Z values. Negative 1884a49301eSmrg * vertex Z values come out as large fragment Z uints. 1894a49301eSmrg */ 1904a49301eSmrg min = (GLint) (min_f * fb->_DepthMaxF); 1914a49301eSmrg max = (GLint) (max_f * fb->_DepthMaxF); 1924a49301eSmrg if (max < 0) 1934a49301eSmrg max = 0x7fffffff; /* catch over flow for 30-bit z */ 1944a49301eSmrg 1954a49301eSmrg /* Note that we do the comparisons here using signed integers. 1964a49301eSmrg */ 1974a49301eSmrg for (i = 0; i < count; i++) { 1984a49301eSmrg if (zValues[i] < min) 1994a49301eSmrg zValues[i] = min; 2004a49301eSmrg if (zValues[i] > max) 2014a49301eSmrg zValues[i] = max; 2024a49301eSmrg } 2034a49301eSmrg} 2044a49301eSmrg 2054a49301eSmrg 206af69d88dSmrg/** 207af69d88dSmrg * Get array of 32-bit z values from the depth buffer. With clipping. 208af69d88dSmrg * Note: the returned values are always in the range [0, 2^32-1]. 2097117f1b4Smrg */ 210af69d88dSmrgstatic void 211af69d88dSmrgget_z32_values(struct gl_context *ctx, struct gl_renderbuffer *rb, 212af69d88dSmrg GLuint count, const GLint x[], const GLint y[], 213af69d88dSmrg GLuint zbuffer[]) 2147117f1b4Smrg{ 215af69d88dSmrg struct swrast_renderbuffer *srb = swrast_renderbuffer(rb); 216af69d88dSmrg const GLint w = rb->Width, h = rb->Height; 217af69d88dSmrg const GLubyte *map = _swrast_pixel_address(rb, 0, 0); 218af69d88dSmrg GLuint i; 2197117f1b4Smrg 220af69d88dSmrg if (rb->Format == MESA_FORMAT_Z_UNORM32) { 221af69d88dSmrg const GLint rowStride = srb->RowStride; 222af69d88dSmrg for (i = 0; i < count; i++) { 223af69d88dSmrg if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { 224af69d88dSmrg zbuffer[i] = *((GLuint *) (map + y[i] * rowStride + x[i] * 4)); 225af69d88dSmrg } 2267117f1b4Smrg } 2277117f1b4Smrg } 2287117f1b4Smrg else { 229af69d88dSmrg const GLint bpp = _mesa_get_format_bytes(rb->Format); 230af69d88dSmrg const GLint rowStride = srb->RowStride; 231af69d88dSmrg for (i = 0; i < count; i++) { 232af69d88dSmrg if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { 233af69d88dSmrg const GLubyte *src = map + y[i] * rowStride+ x[i] * bpp; 234af69d88dSmrg _mesa_unpack_uint_z_row(rb->Format, 1, src, &zbuffer[i]); 235af69d88dSmrg } 2367117f1b4Smrg } 2377117f1b4Smrg } 2387117f1b4Smrg} 2397117f1b4Smrg 2407117f1b4Smrg 2417ec681f3Smrg/** Helper struct for MESA_FORMAT_Z32_FLOAT_S8X24_UINT */ 2427ec681f3Smrgstruct z32f_x24s8 2437ec681f3Smrg{ 2447ec681f3Smrg float z; 2457ec681f3Smrg uint32_t x24s8; 2467ec681f3Smrg}; 2477ec681f3Smrg 2487ec681f3Smrg 2497ec681f3Smrg/** 2507ec681f3Smrg ** Pack uint Z pixels. The incoming src value is always in 2517ec681f3Smrg ** the range [0, 2^32-1]. 2527ec681f3Smrg **/ 2537ec681f3Smrg 2547ec681f3Smrgstatic void 2557ec681f3Smrgpack_uint_S8_UINT_Z24_UNORM(const uint32_t *src, void *dst) 2567ec681f3Smrg{ 2577ec681f3Smrg /* don't disturb the stencil values */ 2587ec681f3Smrg uint32_t *d = ((uint32_t *) dst); 2597ec681f3Smrg uint32_t s = *d & 0xff; 2607ec681f3Smrg uint32_t z = *src & 0xffffff00; 2617ec681f3Smrg *d = z | s; 2627ec681f3Smrg} 2637ec681f3Smrg 2647ec681f3Smrgstatic void 2657ec681f3Smrgpack_uint_Z24_UNORM_S8_UINT(const uint32_t *src, void *dst) 2667ec681f3Smrg{ 2677ec681f3Smrg /* don't disturb the stencil values */ 2687ec681f3Smrg uint32_t *d = ((uint32_t *) dst); 2697ec681f3Smrg uint32_t s = *d & 0xff000000; 2707ec681f3Smrg uint32_t z = *src >> 8; 2717ec681f3Smrg *d = s | z; 2727ec681f3Smrg} 2737ec681f3Smrg 2747ec681f3Smrgstatic void 2757ec681f3Smrgpack_uint_Z_UNORM16(const uint32_t *src, void *dst) 2767ec681f3Smrg{ 2777ec681f3Smrg uint16_t *d = ((uint16_t *) dst); 2787ec681f3Smrg *d = *src >> 16; 2797ec681f3Smrg} 2807ec681f3Smrg 2817ec681f3Smrgstatic void 2827ec681f3Smrgpack_uint_Z_UNORM32(const uint32_t *src, void *dst) 2837ec681f3Smrg{ 2847ec681f3Smrg uint32_t *d = ((uint32_t *) dst); 2857ec681f3Smrg *d = *src; 2867ec681f3Smrg} 2877ec681f3Smrg 2887ec681f3Smrg/** 2897ec681f3Smrg ** Pack uint to Z_FLOAT32 or Z_FLOAT32_X24S8. 2907ec681f3Smrg **/ 2917ec681f3Smrg 2927ec681f3Smrgstatic void 2937ec681f3Smrgpack_uint_Z_FLOAT32(const uint32_t *src, void *dst) 2947ec681f3Smrg{ 2957ec681f3Smrg float *d = ((float *) dst); 2967ec681f3Smrg const double scale = 1.0 / (double) 0xffffffff; 2977ec681f3Smrg *d = (float) (*src * scale); 2987ec681f3Smrg assert(*d >= 0.0f); 2997ec681f3Smrg assert(*d <= 1.0f); 3007ec681f3Smrg} 3017ec681f3Smrg 3027ec681f3Smrg/** Pack a uint32_t Z value to dest address */ 3037ec681f3Smrgtypedef void (*mesa_pack_uint_z_func)(const uint32_t *src, void *dst); 3047ec681f3Smrg 3057ec681f3Smrgstatic mesa_pack_uint_z_func 3067ec681f3Smrgget_pack_uint_z_func(mesa_format format) 3077ec681f3Smrg{ 3087ec681f3Smrg switch (format) { 3097ec681f3Smrg case MESA_FORMAT_S8_UINT_Z24_UNORM: 3107ec681f3Smrg case MESA_FORMAT_X8_UINT_Z24_UNORM: 3117ec681f3Smrg return pack_uint_S8_UINT_Z24_UNORM; 3127ec681f3Smrg case MESA_FORMAT_Z24_UNORM_S8_UINT: 3137ec681f3Smrg case MESA_FORMAT_Z24_UNORM_X8_UINT: 3147ec681f3Smrg return pack_uint_Z24_UNORM_S8_UINT; 3157ec681f3Smrg case MESA_FORMAT_Z_UNORM16: 3167ec681f3Smrg return pack_uint_Z_UNORM16; 3177ec681f3Smrg case MESA_FORMAT_Z_UNORM32: 3187ec681f3Smrg return pack_uint_Z_UNORM32; 3197ec681f3Smrg case MESA_FORMAT_Z_FLOAT32: 3207ec681f3Smrg case MESA_FORMAT_Z32_FLOAT_S8X24_UINT: 3217ec681f3Smrg return pack_uint_Z_FLOAT32; 3227ec681f3Smrg default: 3237ec681f3Smrg unreachable("unexpected format in get_pack_uint_z_func()"); 3247ec681f3Smrg } 3257ec681f3Smrg} 3267ec681f3Smrg 327af69d88dSmrg/** 328af69d88dSmrg * Put an array of 32-bit z values into the depth buffer. 329af69d88dSmrg * Note: the z values are always in the range [0, 2^32-1]. 3307117f1b4Smrg */ 3317117f1b4Smrgstatic void 332af69d88dSmrgput_z32_values(struct gl_context *ctx, struct gl_renderbuffer *rb, 333af69d88dSmrg GLuint count, const GLint x[], const GLint y[], 334af69d88dSmrg const GLuint zvalues[], const GLubyte mask[]) 3357117f1b4Smrg{ 336af69d88dSmrg struct swrast_renderbuffer *srb = swrast_renderbuffer(rb); 337af69d88dSmrg const GLint w = rb->Width, h = rb->Height; 338af69d88dSmrg GLubyte *map = _swrast_pixel_address(rb, 0, 0); 339af69d88dSmrg GLuint i; 3407117f1b4Smrg 341af69d88dSmrg if (rb->Format == MESA_FORMAT_Z_UNORM32) { 342af69d88dSmrg const GLint rowStride = srb->RowStride; 343af69d88dSmrg for (i = 0; i < count; i++) { 344af69d88dSmrg if (mask[i] && x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { 345af69d88dSmrg GLuint *dst = (GLuint *) (map + y[i] * rowStride + x[i] * 4); 346af69d88dSmrg *dst = zvalues[i]; 347af69d88dSmrg } 348af69d88dSmrg } 349af69d88dSmrg } 350af69d88dSmrg else { 3517ec681f3Smrg mesa_pack_uint_z_func packZ = get_pack_uint_z_func(rb->Format); 352af69d88dSmrg const GLint bpp = _mesa_get_format_bytes(rb->Format); 353af69d88dSmrg const GLint rowStride = srb->RowStride; 354af69d88dSmrg for (i = 0; i < count; i++) { 355af69d88dSmrg if (mask[i] && x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { 356af69d88dSmrg void *dst = map + y[i] * rowStride + x[i] * bpp; 357af69d88dSmrg packZ(zvalues + i, dst); 358af69d88dSmrg } 359af69d88dSmrg } 3607117f1b4Smrg } 3617117f1b4Smrg} 3627117f1b4Smrg 3637117f1b4Smrg 364af69d88dSmrg/** 365af69d88dSmrg * Apply depth (Z) buffer testing to the span. 366af69d88dSmrg * \return approx number of pixels that passed (only zero is reliable) 367af69d88dSmrg */ 368af69d88dSmrgGLuint 369af69d88dSmrg_swrast_depth_test_span(struct gl_context *ctx, SWspan *span) 3707117f1b4Smrg{ 3717117f1b4Smrg struct gl_framebuffer *fb = ctx->DrawBuffer; 372af69d88dSmrg struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; 373af69d88dSmrg const GLint bpp = _mesa_get_format_bytes(rb->Format); 374af69d88dSmrg void *zStart; 3757117f1b4Smrg const GLuint count = span->end; 376af69d88dSmrg const GLuint *fragZ = span->array->z; 3777117f1b4Smrg GLubyte *mask = span->array->mask; 378af69d88dSmrg void *zBufferVals; 379af69d88dSmrg GLuint *zBufferTemp = NULL; 380af69d88dSmrg GLuint passed; 381af69d88dSmrg GLuint zBits = _mesa_get_format_bits(rb->Format, GL_DEPTH_BITS); 382af69d88dSmrg GLboolean ztest16 = GL_FALSE; 3837117f1b4Smrg 384af69d88dSmrg if (span->arrayMask & SPAN_XY) 385af69d88dSmrg zStart = NULL; 386af69d88dSmrg else 387af69d88dSmrg zStart = _swrast_pixel_address(rb, span->x, span->y); 388af69d88dSmrg 389af69d88dSmrg if (rb->Format == MESA_FORMAT_Z_UNORM16 && !(span->arrayMask & SPAN_XY)) { 390af69d88dSmrg /* directly read/write row of 16-bit Z values */ 391af69d88dSmrg zBufferVals = zStart; 392af69d88dSmrg ztest16 = GL_TRUE; 393af69d88dSmrg } 394af69d88dSmrg else if (rb->Format == MESA_FORMAT_Z_UNORM32 && !(span->arrayMask & SPAN_XY)) { 395af69d88dSmrg /* directly read/write row of 32-bit Z values */ 396af69d88dSmrg zBufferVals = zStart; 397af69d88dSmrg } 398af69d88dSmrg else { 399af69d88dSmrg /* copy Z buffer values into temp buffer (32-bit Z values) */ 400af69d88dSmrg zBufferTemp = malloc(count * sizeof(GLuint)); 401af69d88dSmrg if (!zBufferTemp) 402af69d88dSmrg return 0; 403af69d88dSmrg 404af69d88dSmrg if (span->arrayMask & SPAN_XY) { 405af69d88dSmrg get_z32_values(ctx, rb, count, 406af69d88dSmrg span->array->x, span->array->y, zBufferTemp); 4077117f1b4Smrg } 4087117f1b4Smrg else { 409af69d88dSmrg _mesa_unpack_uint_z_row(rb->Format, count, zStart, zBufferTemp); 4107117f1b4Smrg } 411af69d88dSmrg 412af69d88dSmrg if (zBits == 24) { 413af69d88dSmrg GLuint i; 414af69d88dSmrg /* Convert depth buffer values from 32 to 24 bits to match the 415af69d88dSmrg * fragment Z values generated by rasterization. 416af69d88dSmrg */ 417af69d88dSmrg for (i = 0; i < count; i++) { 418af69d88dSmrg zBufferTemp[i] >>= 8; 419af69d88dSmrg } 420af69d88dSmrg } 421af69d88dSmrg else if (zBits == 16) { 422af69d88dSmrg GLuint i; 423af69d88dSmrg /* Convert depth buffer values from 32 to 16 bits */ 424af69d88dSmrg for (i = 0; i < count; i++) { 425af69d88dSmrg zBufferTemp[i] >>= 16; 426af69d88dSmrg } 4277117f1b4Smrg } 4287117f1b4Smrg else { 429af69d88dSmrg assert(zBits == 32); 4307117f1b4Smrg } 431af69d88dSmrg 432af69d88dSmrg zBufferVals = zBufferTemp; 4337117f1b4Smrg } 4347117f1b4Smrg 435af69d88dSmrg /* do the depth test either with 16 or 32-bit values */ 436af69d88dSmrg if (ztest16) 437af69d88dSmrg passed = depth_test_span16(ctx, count, zBufferVals, fragZ, mask); 438af69d88dSmrg else 439af69d88dSmrg passed = depth_test_span32(ctx, count, zBufferVals, fragZ, mask); 4407117f1b4Smrg 441af69d88dSmrg if (zBufferTemp) { 442af69d88dSmrg /* need to write temp Z values back into the buffer */ 4437117f1b4Smrg 444af69d88dSmrg /* Convert depth buffer values back to 32-bit values. The least 445af69d88dSmrg * significant bits don't matter since they'll get dropped when 446af69d88dSmrg * they're packed back into the depth buffer. 447af69d88dSmrg */ 448af69d88dSmrg if (zBits == 24) { 449af69d88dSmrg GLuint i; 450af69d88dSmrg for (i = 0; i < count; i++) { 451af69d88dSmrg zBufferTemp[i] = (zBufferTemp[i] << 8); 452af69d88dSmrg } 453af69d88dSmrg } 454af69d88dSmrg else if (zBits == 16) { 455af69d88dSmrg GLuint i; 456af69d88dSmrg for (i = 0; i < count; i++) { 457af69d88dSmrg zBufferTemp[i] = zBufferTemp[i] << 16; 458af69d88dSmrg } 459af69d88dSmrg } 460af69d88dSmrg 461af69d88dSmrg if (span->arrayMask & SPAN_XY) { 462af69d88dSmrg /* random locations */ 463af69d88dSmrg put_z32_values(ctx, rb, count, span->array->x, span->array->y, 464af69d88dSmrg zBufferTemp, mask); 465af69d88dSmrg } 466af69d88dSmrg else { 467af69d88dSmrg /* horizontal row */ 4687ec681f3Smrg mesa_pack_uint_z_func packZ = get_pack_uint_z_func(rb->Format); 469af69d88dSmrg GLubyte *dst = zStart; 470af69d88dSmrg GLuint i; 471af69d88dSmrg for (i = 0; i < count; i++) { 472af69d88dSmrg if (mask[i]) { 473af69d88dSmrg packZ(&zBufferTemp[i], dst); 474af69d88dSmrg } 475af69d88dSmrg dst += bpp; 476af69d88dSmrg } 477af69d88dSmrg } 478af69d88dSmrg 479af69d88dSmrg free(zBufferTemp); 480af69d88dSmrg } 481af69d88dSmrg 482af69d88dSmrg if (passed < count) { 483af69d88dSmrg span->writeAll = GL_FALSE; 484af69d88dSmrg } 485af69d88dSmrg return passed; 4867117f1b4Smrg} 4877117f1b4Smrg 4887117f1b4Smrg 4897117f1b4Smrg/** 4907117f1b4Smrg * GL_EXT_depth_bounds_test extension. 4917117f1b4Smrg * Discard fragments depending on whether the corresponding Z-buffer 4927117f1b4Smrg * values are outside the depth bounds test range. 4937117f1b4Smrg * Note: we test the Z buffer values, not the fragment Z values! 4947117f1b4Smrg * \return GL_TRUE if any fragments pass, GL_FALSE if no fragments pass 4957117f1b4Smrg */ 4967117f1b4SmrgGLboolean 4973464ebd5Sriastradh_swrast_depth_bounds_test( struct gl_context *ctx, SWspan *span ) 4987117f1b4Smrg{ 4997117f1b4Smrg struct gl_framebuffer *fb = ctx->DrawBuffer; 500af69d88dSmrg struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; 501af69d88dSmrg GLubyte *zStart; 50201e04c3fSmrg GLuint zMin = (GLuint)((double)ctx->Depth.BoundsMin * 0xffffffff); 50301e04c3fSmrg GLuint zMax = (GLuint)((double)ctx->Depth.BoundsMax * 0xffffffff); 5047117f1b4Smrg GLubyte *mask = span->array->mask; 5057117f1b4Smrg const GLuint count = span->end; 5067117f1b4Smrg GLuint i; 5077117f1b4Smrg GLboolean anyPass = GL_FALSE; 508af69d88dSmrg GLuint *zBufferTemp; 509af69d88dSmrg const GLuint *zBufferVals; 5107117f1b4Smrg 511af69d88dSmrg zBufferTemp = malloc(count * sizeof(GLuint)); 512af69d88dSmrg if (!zBufferTemp) { 513af69d88dSmrg /* don't generate a stream of OUT_OF_MEMORY errors here */ 514af69d88dSmrg return GL_FALSE; 515af69d88dSmrg } 5167117f1b4Smrg 517af69d88dSmrg if (span->arrayMask & SPAN_XY) 518af69d88dSmrg zStart = NULL; 519af69d88dSmrg else 520af69d88dSmrg zStart = _swrast_pixel_address(rb, span->x, span->y); 521af69d88dSmrg 522af69d88dSmrg if (rb->Format == MESA_FORMAT_Z_UNORM32 && !(span->arrayMask & SPAN_XY)) { 523af69d88dSmrg /* directly access 32-bit values in the depth buffer */ 524af69d88dSmrg zBufferVals = (const GLuint *) zStart; 5257117f1b4Smrg } 5267117f1b4Smrg else { 52701e04c3fSmrg /* Round the bounds to the precision of the zbuffer. */ 52801e04c3fSmrg if (rb->Format == MESA_FORMAT_Z_UNORM16) { 52901e04c3fSmrg zMin = (zMin & 0xffff0000) | (zMin >> 16); 53001e04c3fSmrg zMax = (zMax & 0xffff0000) | (zMax >> 16); 53101e04c3fSmrg } else { 53201e04c3fSmrg /* 24 bits */ 53301e04c3fSmrg zMin = (zMin & 0xffffff00) | (zMin >> 24); 53401e04c3fSmrg zMax = (zMax & 0xffffff00) | (zMax >> 24); 53501e04c3fSmrg } 53601e04c3fSmrg 537af69d88dSmrg /* unpack Z values into a temporary array */ 5387117f1b4Smrg if (span->arrayMask & SPAN_XY) { 539af69d88dSmrg get_z32_values(ctx, rb, count, span->array->x, span->array->y, 540af69d88dSmrg zBufferTemp); 5417117f1b4Smrg } 5427117f1b4Smrg else { 543af69d88dSmrg _mesa_unpack_uint_z_row(rb->Format, count, zStart, zBufferTemp); 5447117f1b4Smrg } 545af69d88dSmrg zBufferVals = zBufferTemp; 546af69d88dSmrg } 5477117f1b4Smrg 548af69d88dSmrg /* Now do the tests */ 549af69d88dSmrg for (i = 0; i < count; i++) { 550af69d88dSmrg if (mask[i]) { 551af69d88dSmrg if (zBufferVals[i] < zMin || zBufferVals[i] > zMax) 552af69d88dSmrg mask[i] = GL_FALSE; 553af69d88dSmrg else 554af69d88dSmrg anyPass = GL_TRUE; 5557117f1b4Smrg } 5567117f1b4Smrg } 5577117f1b4Smrg 558af69d88dSmrg free(zBufferTemp); 559af69d88dSmrg 5607117f1b4Smrg return anyPass; 5617117f1b4Smrg} 5627117f1b4Smrg 5637117f1b4Smrg 5647117f1b4Smrg 5657117f1b4Smrg/**********************************************************************/ 5667117f1b4Smrg/***** Read Depth Buffer *****/ 5677117f1b4Smrg/**********************************************************************/ 5687117f1b4Smrg 5697117f1b4Smrg 5707117f1b4Smrg/** 5717117f1b4Smrg * Read a span of depth values from the given depth renderbuffer, returning 5727117f1b4Smrg * the values as GLfloats. 5737117f1b4Smrg * This function does clipping to prevent reading outside the depth buffer's 574af69d88dSmrg * bounds. 5757117f1b4Smrg */ 5767117f1b4Smrgvoid 577af69d88dSmrg_swrast_read_depth_span_float(struct gl_context *ctx, 578af69d88dSmrg struct gl_renderbuffer *rb, 579af69d88dSmrg GLint n, GLint x, GLint y, GLfloat depth[]) 5807117f1b4Smrg{ 5817117f1b4Smrg if (!rb) { 5827117f1b4Smrg /* really only doing this to prevent FP exceptions later */ 583cdc920a0Smrg memset(depth, 0, n * sizeof(GLfloat)); 5844a49301eSmrg return; 5857117f1b4Smrg } 5867117f1b4Smrg 5877117f1b4Smrg if (y < 0 || y >= (GLint) rb->Height || 5887117f1b4Smrg x + n <= 0 || x >= (GLint) rb->Width) { 5897117f1b4Smrg /* span is completely outside framebuffer */ 590cdc920a0Smrg memset(depth, 0, n * sizeof(GLfloat)); 5917117f1b4Smrg return; 5927117f1b4Smrg } 5937117f1b4Smrg 5947117f1b4Smrg if (x < 0) { 5957117f1b4Smrg GLint dx = -x; 5967117f1b4Smrg GLint i; 5977117f1b4Smrg for (i = 0; i < dx; i++) 5987117f1b4Smrg depth[i] = 0.0; 5997117f1b4Smrg x = 0; 6007117f1b4Smrg n -= dx; 6017117f1b4Smrg depth += dx; 6027117f1b4Smrg } 6037117f1b4Smrg if (x + n > (GLint) rb->Width) { 6047117f1b4Smrg GLint dx = x + n - (GLint) rb->Width; 6057117f1b4Smrg GLint i; 6067117f1b4Smrg for (i = 0; i < dx; i++) 6077117f1b4Smrg depth[n - i - 1] = 0.0; 6087117f1b4Smrg n -= dx; 6097117f1b4Smrg } 6107117f1b4Smrg if (n <= 0) { 6117117f1b4Smrg return; 6127117f1b4Smrg } 6137117f1b4Smrg 614af69d88dSmrg _mesa_unpack_float_z_row(rb->Format, n, _swrast_pixel_address(rb, x, y), 615af69d88dSmrg depth); 6167117f1b4Smrg} 6177117f1b4Smrg 6187117f1b4Smrg 6197117f1b4Smrg/** 620af69d88dSmrg * Clear the given z/depth renderbuffer. If the buffer is a combined 621af69d88dSmrg * depth+stencil buffer, only the Z bits will be touched. 6227117f1b4Smrg */ 6237117f1b4Smrgvoid 624af69d88dSmrg_swrast_clear_depth_buffer(struct gl_context *ctx) 6257117f1b4Smrg{ 626af69d88dSmrg struct gl_renderbuffer *rb = 627af69d88dSmrg ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 628af69d88dSmrg GLint x, y, width, height; 629af69d88dSmrg GLubyte *map; 630af69d88dSmrg GLint rowStride, i, j; 631af69d88dSmrg GLbitfield mapMode; 6324a49301eSmrg 633af69d88dSmrg if (!rb || !ctx->Depth.Mask) { 634af69d88dSmrg /* no depth buffer, or writing to it is disabled */ 6354a49301eSmrg return; 6367117f1b4Smrg } 6377117f1b4Smrg 638af69d88dSmrg /* compute region to clear */ 639af69d88dSmrg x = ctx->DrawBuffer->_Xmin; 640af69d88dSmrg y = ctx->DrawBuffer->_Ymin; 641af69d88dSmrg width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; 642af69d88dSmrg height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; 6437117f1b4Smrg 644af69d88dSmrg mapMode = GL_MAP_WRITE_BIT; 645af69d88dSmrg if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || 646af69d88dSmrg rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT || 647af69d88dSmrg rb->Format == MESA_FORMAT_S8_UINT_Z24_UNORM || 648af69d88dSmrg rb->Format == MESA_FORMAT_X8_UINT_Z24_UNORM) { 649af69d88dSmrg mapMode |= GL_MAP_READ_BIT; 6507117f1b4Smrg } 6517117f1b4Smrg 652af69d88dSmrg ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, 65301e04c3fSmrg mapMode, &map, &rowStride, 65401e04c3fSmrg ctx->DrawBuffer->FlipY); 655af69d88dSmrg if (!map) { 656af69d88dSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(depth)"); 6577117f1b4Smrg return; 6587117f1b4Smrg } 6597117f1b4Smrg 660af69d88dSmrg switch (rb->Format) { 661af69d88dSmrg case MESA_FORMAT_Z_UNORM16: 662af69d88dSmrg { 663af69d88dSmrg GLfloat clear = (GLfloat) ctx->Depth.Clear; 664af69d88dSmrg GLushort clearVal = 0; 665af69d88dSmrg _mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal); 666af69d88dSmrg if (clearVal == 0xffff && width * 2 == rowStride) { 667af69d88dSmrg /* common case */ 668af69d88dSmrg memset(map, 0xff, width * height * 2); 669af69d88dSmrg } 670af69d88dSmrg else { 671af69d88dSmrg for (i = 0; i < height; i++) { 672af69d88dSmrg GLushort *row = (GLushort *) map; 673af69d88dSmrg for (j = 0; j < width; j++) { 674af69d88dSmrg row[j] = clearVal; 675af69d88dSmrg } 676af69d88dSmrg map += rowStride; 677af69d88dSmrg } 6787117f1b4Smrg } 6797117f1b4Smrg } 680af69d88dSmrg break; 681af69d88dSmrg case MESA_FORMAT_Z_UNORM32: 682af69d88dSmrg case MESA_FORMAT_Z_FLOAT32: 683af69d88dSmrg { 684af69d88dSmrg GLfloat clear = (GLfloat) ctx->Depth.Clear; 685af69d88dSmrg GLuint clearVal = 0; 686af69d88dSmrg _mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal); 687af69d88dSmrg for (i = 0; i < height; i++) { 688af69d88dSmrg GLuint *row = (GLuint *) map; 689af69d88dSmrg for (j = 0; j < width; j++) { 690af69d88dSmrg row[j] = clearVal; 691af69d88dSmrg } 692af69d88dSmrg map += rowStride; 6937117f1b4Smrg } 6947117f1b4Smrg } 695af69d88dSmrg break; 696af69d88dSmrg case MESA_FORMAT_Z24_UNORM_S8_UINT: 697af69d88dSmrg case MESA_FORMAT_Z24_UNORM_X8_UINT: 698af69d88dSmrg case MESA_FORMAT_S8_UINT_Z24_UNORM: 699af69d88dSmrg case MESA_FORMAT_X8_UINT_Z24_UNORM: 700af69d88dSmrg { 701af69d88dSmrg GLfloat clear = (GLfloat) ctx->Depth.Clear; 702af69d88dSmrg GLuint clearVal = 0; 703af69d88dSmrg GLuint mask; 704af69d88dSmrg 705af69d88dSmrg if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT || 706af69d88dSmrg rb->Format == MESA_FORMAT_Z24_UNORM_X8_UINT) 707af69d88dSmrg mask = 0xff000000; 708af69d88dSmrg else 709af69d88dSmrg mask = 0xff; 710af69d88dSmrg 711af69d88dSmrg _mesa_pack_float_z_row(rb->Format, 1, &clear, &clearVal); 712af69d88dSmrg for (i = 0; i < height; i++) { 713af69d88dSmrg GLuint *row = (GLuint *) map; 714af69d88dSmrg for (j = 0; j < width; j++) { 715af69d88dSmrg row[j] = (row[j] & mask) | clearVal; 716af69d88dSmrg } 717af69d88dSmrg map += rowStride; 7187117f1b4Smrg } 719af69d88dSmrg 7207117f1b4Smrg } 721af69d88dSmrg break; 722af69d88dSmrg case MESA_FORMAT_Z32_FLOAT_S8X24_UINT: 723af69d88dSmrg /* XXX untested */ 724af69d88dSmrg { 725af69d88dSmrg GLfloat clearVal = (GLfloat) ctx->Depth.Clear; 726af69d88dSmrg for (i = 0; i < height; i++) { 727af69d88dSmrg GLfloat *row = (GLfloat *) map; 728af69d88dSmrg for (j = 0; j < width; j++) { 729af69d88dSmrg row[j * 2] = clearVal; 730af69d88dSmrg } 731af69d88dSmrg map += rowStride; 732af69d88dSmrg } 733af69d88dSmrg } 734af69d88dSmrg break; 735af69d88dSmrg default: 736af69d88dSmrg _mesa_problem(ctx, "Unexpected depth buffer format %s" 737af69d88dSmrg " in _swrast_clear_depth_buffer()", 738af69d88dSmrg _mesa_get_format_name(rb->Format)); 7397117f1b4Smrg } 740af69d88dSmrg 741af69d88dSmrg ctx->Driver.UnmapRenderbuffer(ctx, rb); 7427117f1b4Smrg} 7437117f1b4Smrg 7447117f1b4Smrg 7457117f1b4Smrg 746af69d88dSmrg 7477117f1b4Smrg/** 748af69d88dSmrg * Clear both depth and stencil values in a combined depth+stencil buffer. 7497117f1b4Smrg */ 7507117f1b4Smrgvoid 751af69d88dSmrg_swrast_clear_depth_stencil_buffer(struct gl_context *ctx) 7527117f1b4Smrg{ 753af69d88dSmrg const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits; 754af69d88dSmrg const GLuint writeMask = ctx->Stencil.WriteMask[0]; 755af69d88dSmrg const GLuint stencilMax = (1 << stencilBits) - 1; 756af69d88dSmrg struct gl_renderbuffer *rb = 757af69d88dSmrg ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 7587117f1b4Smrg GLint x, y, width, height; 759af69d88dSmrg GLbitfield mapMode; 760af69d88dSmrg GLubyte *map; 761af69d88dSmrg GLint rowStride, i, j; 7627117f1b4Smrg 763af69d88dSmrg /* check that we really have a combined depth+stencil buffer */ 764af69d88dSmrg assert(rb == ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer); 7657117f1b4Smrg 7667117f1b4Smrg /* compute region to clear */ 7677117f1b4Smrg x = ctx->DrawBuffer->_Xmin; 7687117f1b4Smrg y = ctx->DrawBuffer->_Ymin; 7697117f1b4Smrg width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; 7707117f1b4Smrg height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; 7717117f1b4Smrg 772af69d88dSmrg mapMode = GL_MAP_WRITE_BIT; 773af69d88dSmrg if ((writeMask & stencilMax) != stencilMax) { 774af69d88dSmrg /* need to mask stencil values */ 775af69d88dSmrg mapMode |= GL_MAP_READ_BIT; 776af69d88dSmrg } 777af69d88dSmrg 778af69d88dSmrg ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, 77901e04c3fSmrg mapMode, &map, &rowStride, 78001e04c3fSmrg ctx->DrawBuffer->FlipY); 781af69d88dSmrg if (!map) { 782af69d88dSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(depth+stencil)"); 783af69d88dSmrg return; 784af69d88dSmrg } 785af69d88dSmrg 786af69d88dSmrg switch (rb->Format) { 787af69d88dSmrg case MESA_FORMAT_Z24_UNORM_S8_UINT: 788af69d88dSmrg case MESA_FORMAT_S8_UINT_Z24_UNORM: 789af69d88dSmrg { 790af69d88dSmrg GLfloat zClear = (GLfloat) ctx->Depth.Clear; 791af69d88dSmrg GLuint clear = 0, mask; 792af69d88dSmrg 793af69d88dSmrg _mesa_pack_float_z_row(rb->Format, 1, &zClear, &clear); 794af69d88dSmrg 795af69d88dSmrg if (rb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT) { 796af69d88dSmrg mask = ((~writeMask) & 0xff) << 24; 797af69d88dSmrg clear |= (ctx->Stencil.Clear & writeMask & 0xff) << 24; 7987117f1b4Smrg } 7997117f1b4Smrg else { 800af69d88dSmrg mask = ((~writeMask) & 0xff); 801af69d88dSmrg clear |= (ctx->Stencil.Clear & writeMask & 0xff); 802af69d88dSmrg } 803af69d88dSmrg 804af69d88dSmrg for (i = 0; i < height; i++) { 805af69d88dSmrg GLuint *row = (GLuint *) map; 806af69d88dSmrg if (mask != 0x0) { 8077117f1b4Smrg for (j = 0; j < width; j++) { 808af69d88dSmrg row[j] = (row[j] & mask) | clear; 8097117f1b4Smrg } 8107117f1b4Smrg } 811af69d88dSmrg else { 812af69d88dSmrg for (j = 0; j < width; j++) { 813af69d88dSmrg row[j] = clear; 814af69d88dSmrg } 815af69d88dSmrg } 816af69d88dSmrg map += rowStride; 8177117f1b4Smrg } 8187117f1b4Smrg } 819af69d88dSmrg break; 820af69d88dSmrg case MESA_FORMAT_Z32_FLOAT_S8X24_UINT: 821af69d88dSmrg /* XXX untested */ 822af69d88dSmrg { 823af69d88dSmrg const GLfloat zClear = (GLfloat) ctx->Depth.Clear; 824af69d88dSmrg const GLuint sClear = ctx->Stencil.Clear & writeMask; 825af69d88dSmrg const GLuint sMask = (~writeMask) & 0xff; 8267117f1b4Smrg for (i = 0; i < height; i++) { 827af69d88dSmrg GLfloat *zRow = (GLfloat *) map; 828af69d88dSmrg GLuint *sRow = (GLuint *) map; 8297117f1b4Smrg for (j = 0; j < width; j++) { 830af69d88dSmrg zRow[j * 2 + 0] = zClear; 8317117f1b4Smrg } 832af69d88dSmrg if (sMask != 0) { 833af69d88dSmrg for (j = 0; j < width; j++) { 834af69d88dSmrg sRow[j * 2 + 1] = (sRow[j * 2 + 1] & sMask) | sClear; 835af69d88dSmrg } 836af69d88dSmrg } 837af69d88dSmrg else { 838af69d88dSmrg for (j = 0; j < width; j++) { 839af69d88dSmrg sRow[j * 2 + 1] = sClear; 840af69d88dSmrg } 841af69d88dSmrg } 842af69d88dSmrg map += rowStride; 8437117f1b4Smrg } 8447117f1b4Smrg } 845af69d88dSmrg break; 846af69d88dSmrg default: 847af69d88dSmrg _mesa_problem(ctx, "Unexpected depth buffer format %s" 848af69d88dSmrg " in _swrast_clear_depth_buffer()", 849af69d88dSmrg _mesa_get_format_name(rb->Format)); 8507117f1b4Smrg } 851af69d88dSmrg 852af69d88dSmrg ctx->Driver.UnmapRenderbuffer(ctx, rb); 853af69d88dSmrg 8547117f1b4Smrg} 855