sp_quad_depth_test.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00032 #include "pipe/p_defines.h"
00033 #include "util/u_memory.h"
00034 #include "sp_context.h"
00035 #include "sp_headers.h"
00036 #include "sp_surface.h"
00037 #include "sp_quad.h"
00038 #include "sp_tile_cache.h"
00039 
00040 
00046 /*
00047  * To increase efficiency, we should probably have multiple versions
00048  * of this function that are specifically for Z16, Z32 and FP Z buffers.
00049  * Try to effectively do that with codegen...
00050  */
00051 
00052 void
00053 sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
00054 {
00055    struct softpipe_context *softpipe = qs->softpipe;
00056    struct pipe_surface *ps = softpipe->framebuffer.zsbuf;
00057    const enum pipe_format format = ps->format;
00058    unsigned bzzzz[QUAD_SIZE];  
00059    unsigned qzzzz[QUAD_SIZE];  
00060    unsigned zmask = 0;
00061    unsigned j;
00062    struct softpipe_cached_tile *tile
00063       = sp_get_cached_tile(softpipe, softpipe->zsbuf_cache, quad->input.x0, quad->input.y0);
00064 
00065    assert(ps); /* shouldn't get here if there's no zbuffer */
00066 
00067    /*
00068     * Convert quad's float depth values to int depth values (qzzzz).
00069     * If the Z buffer stores integer values, we _have_ to do the depth
00070     * compares with integers (not floats).  Otherwise, the float->int->float
00071     * conversion of Z values (which isn't an identity function) will cause
00072     * Z-fighting errors.
00073     *
00074     * Also, get the zbuffer values (bzzzz) from the cached tile.
00075     */
00076    switch (format) {
00077    case PIPE_FORMAT_Z16_UNORM:
00078       {
00079          float scale = 65535.0;
00080 
00081          for (j = 0; j < QUAD_SIZE; j++) {
00082             qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
00083          }
00084 
00085          for (j = 0; j < QUAD_SIZE; j++) {
00086             int x = quad->input.x0 % TILE_SIZE + (j & 1);
00087             int y = quad->input.y0 % TILE_SIZE + (j >> 1);
00088             bzzzz[j] = tile->data.depth16[y][x];
00089          }
00090       }
00091       break;
00092    case PIPE_FORMAT_Z32_UNORM:
00093       {
00094          double scale = (double) (uint) ~0UL;
00095 
00096          for (j = 0; j < QUAD_SIZE; j++) {
00097             qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
00098          }
00099 
00100          for (j = 0; j < QUAD_SIZE; j++) {
00101             int x = quad->input.x0 % TILE_SIZE + (j & 1);
00102             int y = quad->input.y0 % TILE_SIZE + (j >> 1);
00103             bzzzz[j] = tile->data.depth32[y][x];
00104          }
00105       }
00106       break;
00107    case PIPE_FORMAT_X8Z24_UNORM:
00108       /* fall-through */
00109    case PIPE_FORMAT_S8Z24_UNORM:
00110       {
00111          float scale = (float) ((1 << 24) - 1);
00112 
00113          for (j = 0; j < QUAD_SIZE; j++) {
00114             qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
00115          }
00116 
00117          for (j = 0; j < QUAD_SIZE; j++) {
00118             int x = quad->input.x0 % TILE_SIZE + (j & 1);
00119             int y = quad->input.y0 % TILE_SIZE + (j >> 1);
00120             bzzzz[j] = tile->data.depth32[y][x] & 0xffffff;
00121          }
00122       }
00123       break;
00124    case PIPE_FORMAT_Z24X8_UNORM:
00125       /* fall-through */
00126    case PIPE_FORMAT_Z24S8_UNORM:
00127       {
00128          float scale = (float) ((1 << 24) - 1);
00129 
00130          for (j = 0; j < QUAD_SIZE; j++) {
00131             qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
00132          }
00133 
00134          for (j = 0; j < QUAD_SIZE; j++) {
00135             int x = quad->input.x0 % TILE_SIZE + (j & 1);
00136             int y = quad->input.y0 % TILE_SIZE + (j >> 1);
00137             bzzzz[j] = tile->data.depth32[y][x] >> 8;
00138          }
00139       }
00140       break;
00141    default:
00142       assert(0);
00143    }
00144 
00145    switch (softpipe->depth_stencil->depth.func) {
00146    case PIPE_FUNC_NEVER:
00147       /* zmask = 0 */
00148       break;
00149    case PIPE_FUNC_LESS:
00150       /* Note this is pretty much a single sse or cell instruction.  
00151        * Like this:  quad->mask &= (quad->outputs.depth < zzzz);
00152        */
00153       for (j = 0; j < QUAD_SIZE; j++) {
00154          if (qzzzz[j] < bzzzz[j]) 
00155             zmask |= 1 << j;
00156       }
00157       break;
00158    case PIPE_FUNC_EQUAL:
00159       for (j = 0; j < QUAD_SIZE; j++) {
00160          if (qzzzz[j] == bzzzz[j]) 
00161             zmask |= 1 << j;
00162       }
00163       break;
00164    case PIPE_FUNC_LEQUAL:
00165       for (j = 0; j < QUAD_SIZE; j++) {
00166          if (qzzzz[j] <= bzzzz[j]) 
00167             zmask |= (1 << j);
00168       }
00169       break;
00170    case PIPE_FUNC_GREATER:
00171       for (j = 0; j < QUAD_SIZE; j++) {
00172          if (qzzzz[j] > bzzzz[j]) 
00173             zmask |= (1 << j);
00174       }
00175       break;
00176    case PIPE_FUNC_NOTEQUAL:
00177       for (j = 0; j < QUAD_SIZE; j++) {
00178          if (qzzzz[j] != bzzzz[j]) 
00179             zmask |= (1 << j);
00180       }
00181       break;
00182    case PIPE_FUNC_GEQUAL:
00183       for (j = 0; j < QUAD_SIZE; j++) {
00184          if (qzzzz[j] >= bzzzz[j]) 
00185             zmask |= (1 << j);
00186       }
00187       break;
00188    case PIPE_FUNC_ALWAYS:
00189       zmask = MASK_ALL;
00190       break;
00191    default:
00192       assert(0);
00193    }
00194 
00195    quad->inout.mask &= zmask;
00196 
00197    if (softpipe->depth_stencil->depth.writemask) {
00198       
00199       /* This is also efficient with sse / spe instructions: 
00200        */
00201       for (j = 0; j < QUAD_SIZE; j++) {
00202          if (quad->inout.mask & (1 << j)) {
00203             bzzzz[j] = qzzzz[j];
00204          }
00205       }
00206 
00207       /* put updated Z values back into cached tile */
00208       switch (format) {
00209       case PIPE_FORMAT_Z16_UNORM:
00210          for (j = 0; j < QUAD_SIZE; j++) {
00211             int x = quad->input.x0 % TILE_SIZE + (j & 1);
00212             int y = quad->input.y0 % TILE_SIZE + (j >> 1);
00213             tile->data.depth16[y][x] = (ushort) bzzzz[j];
00214          }
00215          break;
00216       case PIPE_FORMAT_X8Z24_UNORM:
00217          /* fall-through */
00218          /* (yes, this falls through to a different case than above) */
00219       case PIPE_FORMAT_Z32_UNORM:
00220          for (j = 0; j < QUAD_SIZE; j++) {
00221             int x = quad->input.x0 % TILE_SIZE + (j & 1);
00222             int y = quad->input.y0 % TILE_SIZE + (j >> 1);
00223             tile->data.depth32[y][x] = bzzzz[j];
00224          }
00225          break;
00226       case PIPE_FORMAT_S8Z24_UNORM:
00227          for (j = 0; j < QUAD_SIZE; j++) {
00228             int x = quad->input.x0 % TILE_SIZE + (j & 1);
00229             int y = quad->input.y0 % TILE_SIZE + (j >> 1);
00230             uint s8z24 = tile->data.depth32[y][x];
00231             s8z24 = (s8z24 & 0xff000000) | bzzzz[j];
00232             tile->data.depth32[y][x] = s8z24;
00233          }
00234          break;
00235       case PIPE_FORMAT_Z24S8_UNORM:
00236          for (j = 0; j < QUAD_SIZE; j++) {
00237             int x = quad->input.x0 % TILE_SIZE + (j & 1);
00238             int y = quad->input.y0 % TILE_SIZE + (j >> 1);
00239             uint z24s8 = tile->data.depth32[y][x];
00240             z24s8 = (z24s8 & 0xff) | (bzzzz[j] << 8);
00241             tile->data.depth32[y][x] = z24s8;
00242          }
00243          break;
00244       case PIPE_FORMAT_Z24X8_UNORM:
00245          for (j = 0; j < QUAD_SIZE; j++) {
00246             int x = quad->input.x0 % TILE_SIZE + (j & 1);
00247             int y = quad->input.y0 % TILE_SIZE + (j >> 1);
00248             tile->data.depth32[y][x] = bzzzz[j] << 8;
00249          }
00250          break;
00251       default:
00252          assert(0);
00253       }
00254    }
00255 }
00256 
00257 
00258 static void
00259 depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
00260 {
00261    sp_depth_test_quad(qs, quad);
00262 
00263    if (quad->inout.mask)
00264       qs->next->run(qs->next, quad);
00265 }
00266 
00267 
00268 static void depth_test_begin(struct quad_stage *qs)
00269 {
00270    qs->next->begin(qs->next);
00271 }
00272 
00273 
00274 static void depth_test_destroy(struct quad_stage *qs)
00275 {
00276    FREE( qs );
00277 }
00278 
00279 
00280 struct quad_stage *sp_quad_depth_test_stage( struct softpipe_context *softpipe )
00281 {
00282    struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
00283 
00284    stage->softpipe = softpipe;
00285    stage->begin = depth_test_begin;
00286    stage->run = depth_test_quad;
00287    stage->destroy = depth_test_destroy;
00288 
00289    return stage;
00290 }

Generated on Tue Sep 29 06:25:17 2009 for Gallium3D by  doxygen 1.5.4