mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-01 05:58:05 +02:00
llvmpipe: move all depth/stencil/alpha pixel processing into one stage
This commit is contained in:
parent
b8c437f20f
commit
05bfd93c3f
13 changed files with 586 additions and 963 deletions
|
|
@ -19,13 +19,8 @@ C_SOURCES = \
|
|||
lp_prim_vbuf.c \
|
||||
lp_quad_pipe.c \
|
||||
lp_quad_stipple.c \
|
||||
lp_quad_earlyz.c \
|
||||
lp_quad_depth_test.c \
|
||||
lp_quad_stencil.c \
|
||||
lp_quad_fs.c \
|
||||
lp_quad_alpha_test.c \
|
||||
lp_quad_occlusion.c \
|
||||
lp_quad_coverage.c \
|
||||
lp_quad_blend.c \
|
||||
lp_screen.c \
|
||||
lp_setup.c \
|
||||
|
|
|
|||
|
|
@ -88,14 +88,8 @@ static void llvmpipe_destroy( struct pipe_context *pipe )
|
|||
if (llvmpipe->draw)
|
||||
draw_destroy( llvmpipe->draw );
|
||||
|
||||
llvmpipe->quad.polygon_stipple->destroy( llvmpipe->quad.polygon_stipple );
|
||||
llvmpipe->quad.earlyz->destroy( llvmpipe->quad.earlyz );
|
||||
llvmpipe->quad.shade->destroy( llvmpipe->quad.shade );
|
||||
llvmpipe->quad.alpha_test->destroy( llvmpipe->quad.alpha_test );
|
||||
llvmpipe->quad.depth_test->destroy( llvmpipe->quad.depth_test );
|
||||
llvmpipe->quad.stencil_test->destroy( llvmpipe->quad.stencil_test );
|
||||
llvmpipe->quad.occlusion->destroy( llvmpipe->quad.occlusion );
|
||||
llvmpipe->quad.coverage->destroy( llvmpipe->quad.coverage );
|
||||
llvmpipe->quad.blend->destroy( llvmpipe->quad.blend );
|
||||
|
||||
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
|
||||
|
|
@ -230,14 +224,8 @@ llvmpipe_create( struct pipe_screen *screen )
|
|||
|
||||
|
||||
/* setup quad rendering stages */
|
||||
llvmpipe->quad.polygon_stipple = lp_quad_polygon_stipple_stage(llvmpipe);
|
||||
llvmpipe->quad.earlyz = lp_quad_earlyz_stage(llvmpipe);
|
||||
llvmpipe->quad.shade = lp_quad_shade_stage(llvmpipe);
|
||||
llvmpipe->quad.alpha_test = lp_quad_alpha_test_stage(llvmpipe);
|
||||
llvmpipe->quad.depth_test = lp_quad_depth_test_stage(llvmpipe);
|
||||
llvmpipe->quad.stencil_test = lp_quad_stencil_test_stage(llvmpipe);
|
||||
llvmpipe->quad.occlusion = lp_quad_occlusion_stage(llvmpipe);
|
||||
llvmpipe->quad.coverage = lp_quad_coverage_stage(llvmpipe);
|
||||
llvmpipe->quad.blend = lp_quad_blend_stage(llvmpipe);
|
||||
|
||||
/* vertex shader samplers */
|
||||
|
|
|
|||
|
|
@ -114,14 +114,8 @@ struct llvmpipe_context {
|
|||
|
||||
/** Software quad rendering pipeline */
|
||||
struct {
|
||||
struct quad_stage *polygon_stipple;
|
||||
struct quad_stage *earlyz;
|
||||
struct quad_stage *shade;
|
||||
struct quad_stage *alpha_test;
|
||||
struct quad_stage *stencil_test;
|
||||
struct quad_stage *depth_test;
|
||||
struct quad_stage *occlusion;
|
||||
struct quad_stage *coverage;
|
||||
struct quad_stage *blend;
|
||||
|
||||
struct quad_stage *first; /**< points to one of the above stages */
|
||||
|
|
|
|||
|
|
@ -1,112 +0,0 @@
|
|||
|
||||
/**
|
||||
* quad alpha test
|
||||
*/
|
||||
|
||||
#include "lp_context.h"
|
||||
#include "lp_quad.h"
|
||||
#include "lp_quad_pipe.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "util/u_memory.h"
|
||||
|
||||
#define ALPHATEST( FUNC, COMP ) \
|
||||
static void \
|
||||
alpha_test_quads_##FUNC( struct quad_stage *qs, \
|
||||
struct quad_header *quads[], \
|
||||
unsigned nr ) \
|
||||
{ \
|
||||
const float ref = qs->llvmpipe->depth_stencil->alpha.ref_value; \
|
||||
const uint cbuf = 0; /* only output[0].alpha is tested */ \
|
||||
unsigned pass_nr = 0; \
|
||||
unsigned i; \
|
||||
\
|
||||
for (i = 0; i < nr; i++) { \
|
||||
const float *aaaa = quads[i]->output.color[cbuf][3]; \
|
||||
unsigned passMask = 0; \
|
||||
\
|
||||
if (aaaa[0] COMP ref) passMask |= (1 << 0); \
|
||||
if (aaaa[1] COMP ref) passMask |= (1 << 1); \
|
||||
if (aaaa[2] COMP ref) passMask |= (1 << 2); \
|
||||
if (aaaa[3] COMP ref) passMask |= (1 << 3); \
|
||||
\
|
||||
quads[i]->inout.mask &= passMask; \
|
||||
\
|
||||
if (quads[i]->inout.mask) \
|
||||
quads[pass_nr++] = quads[i]; \
|
||||
} \
|
||||
\
|
||||
if (pass_nr) \
|
||||
qs->next->run(qs->next, quads, pass_nr); \
|
||||
}
|
||||
|
||||
|
||||
ALPHATEST( LESS, < )
|
||||
ALPHATEST( EQUAL, == )
|
||||
ALPHATEST( LEQUAL, <= )
|
||||
ALPHATEST( GREATER, > )
|
||||
ALPHATEST( NOTEQUAL, != )
|
||||
ALPHATEST( GEQUAL, >= )
|
||||
|
||||
|
||||
/* XXX: Incorporate into shader using KILP.
|
||||
*/
|
||||
static void
|
||||
alpha_test_quad(struct quad_stage *qs,
|
||||
struct quad_header *quads[],
|
||||
unsigned nr)
|
||||
{
|
||||
switch (qs->llvmpipe->depth_stencil->alpha.func) {
|
||||
case PIPE_FUNC_LESS:
|
||||
alpha_test_quads_LESS( qs, quads, nr );
|
||||
break;
|
||||
case PIPE_FUNC_EQUAL:
|
||||
alpha_test_quads_EQUAL( qs, quads, nr );
|
||||
break;
|
||||
case PIPE_FUNC_LEQUAL:
|
||||
alpha_test_quads_LEQUAL( qs, quads, nr );
|
||||
break;
|
||||
case PIPE_FUNC_GREATER:
|
||||
alpha_test_quads_GREATER( qs, quads, nr );
|
||||
break;
|
||||
case PIPE_FUNC_NOTEQUAL:
|
||||
alpha_test_quads_NOTEQUAL( qs, quads, nr );
|
||||
break;
|
||||
case PIPE_FUNC_GEQUAL:
|
||||
alpha_test_quads_GEQUAL( qs, quads, nr );
|
||||
break;
|
||||
case PIPE_FUNC_ALWAYS:
|
||||
assert(0); /* should be caught earlier */
|
||||
qs->next->run(qs->next, quads, nr);
|
||||
break;
|
||||
case PIPE_FUNC_NEVER:
|
||||
default:
|
||||
assert(0); /* should be caught earlier */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void alpha_test_begin(struct quad_stage *qs)
|
||||
{
|
||||
qs->next->begin(qs->next);
|
||||
}
|
||||
|
||||
|
||||
static void alpha_test_destroy(struct quad_stage *qs)
|
||||
{
|
||||
FREE( qs );
|
||||
}
|
||||
|
||||
|
||||
struct quad_stage *
|
||||
lp_quad_alpha_test_stage( struct llvmpipe_context *llvmpipe )
|
||||
{
|
||||
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
|
||||
|
||||
stage->llvmpipe = llvmpipe;
|
||||
stage->begin = alpha_test_begin;
|
||||
stage->run = alpha_test_quad;
|
||||
stage->destroy = alpha_test_destroy;
|
||||
|
||||
return stage;
|
||||
}
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* \brief Apply AA coverage to quad alpha valus
|
||||
* \author Brian Paul
|
||||
*/
|
||||
|
||||
|
||||
#include "pipe/p_defines.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "lp_context.h"
|
||||
#include "lp_quad.h"
|
||||
#include "lp_quad_pipe.h"
|
||||
|
||||
|
||||
/**
|
||||
* Multiply quad's alpha values by the fragment coverage.
|
||||
*/
|
||||
static INLINE void
|
||||
coverage_quad(struct quad_stage *qs, struct quad_header *quad)
|
||||
{
|
||||
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
|
||||
uint cbuf;
|
||||
|
||||
/* loop over colorbuffer outputs */
|
||||
for (cbuf = 0; cbuf < llvmpipe->framebuffer.nr_cbufs; cbuf++) {
|
||||
float (*quadColor)[4] = quad->output.color[cbuf];
|
||||
unsigned j;
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
assert(quad->input.coverage[j] >= 0.0);
|
||||
assert(quad->input.coverage[j] <= 1.0);
|
||||
quadColor[3][j] *= quad->input.coverage[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* XXX: Incorporate into shader after alpha_test.
|
||||
*/
|
||||
static void
|
||||
coverage_run(struct quad_stage *qs,
|
||||
struct quad_header *quads[],
|
||||
unsigned nr)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < nr; i++)
|
||||
coverage_quad( qs, quads[i] );
|
||||
|
||||
qs->next->run(qs->next, quads, nr);
|
||||
}
|
||||
|
||||
static void coverage_begin(struct quad_stage *qs)
|
||||
{
|
||||
qs->next->begin(qs->next);
|
||||
}
|
||||
|
||||
|
||||
static void coverage_destroy(struct quad_stage *qs)
|
||||
{
|
||||
FREE( qs );
|
||||
}
|
||||
|
||||
|
||||
struct quad_stage *lp_quad_coverage_stage( struct llvmpipe_context *llvmpipe )
|
||||
{
|
||||
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
|
||||
|
||||
stage->llvmpipe = llvmpipe;
|
||||
stage->begin = coverage_begin;
|
||||
stage->run = coverage_run;
|
||||
stage->destroy = coverage_destroy;
|
||||
|
||||
return stage;
|
||||
}
|
||||
|
|
@ -31,61 +31,109 @@
|
|||
|
||||
#include "pipe/p_defines.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "tgsi/tgsi_scan.h"
|
||||
#include "lp_context.h"
|
||||
#include "lp_quad.h"
|
||||
#include "lp_surface.h"
|
||||
#include "lp_quad_pipe.h"
|
||||
#include "lp_tile_cache.h"
|
||||
#include "lp_state.h" /* for lp_fragment_shader */
|
||||
|
||||
|
||||
/**
|
||||
* Do depth testing for a quad.
|
||||
* Not static since it's used by the stencil code.
|
||||
*/
|
||||
|
||||
/*
|
||||
* To increase efficiency, we should probably have multiple versions
|
||||
* of this function that are specifically for Z16, Z32 and FP Z buffers.
|
||||
* Try to effectively do that with codegen...
|
||||
*/
|
||||
|
||||
boolean
|
||||
lp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
|
||||
{
|
||||
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
|
||||
struct pipe_surface *ps = llvmpipe->framebuffer.zsbuf;
|
||||
const enum pipe_format format = ps->format;
|
||||
struct depth_data {
|
||||
struct pipe_surface *ps;
|
||||
enum pipe_format format;
|
||||
unsigned bzzzz[QUAD_SIZE]; /**< Z values fetched from depth buffer */
|
||||
unsigned qzzzz[QUAD_SIZE]; /**< Z values from the quad */
|
||||
unsigned zmask = 0;
|
||||
ubyte stencilVals[QUAD_SIZE];
|
||||
struct llvmpipe_cached_tile *tile;
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void
|
||||
get_depth_stencil_values( struct depth_data *data,
|
||||
const struct quad_header *quad )
|
||||
{
|
||||
unsigned j;
|
||||
struct llvmpipe_cached_tile *tile
|
||||
= lp_get_cached_tile(llvmpipe->zsbuf_cache, quad->input.x0, quad->input.y0);
|
||||
const struct llvmpipe_cached_tile *tile = data->tile;
|
||||
|
||||
assert(ps); /* shouldn't get here if there's no zbuffer */
|
||||
switch (data->format) {
|
||||
case PIPE_FORMAT_Z16_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
data->bzzzz[j] = tile->data.depth16[y][x];
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_Z32_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
data->bzzzz[j] = tile->data.depth32[y][x];
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_X8Z24_UNORM:
|
||||
case PIPE_FORMAT_S8Z24_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
data->bzzzz[j] = tile->data.depth32[y][x] & 0xffffff;
|
||||
data->stencilVals[j] = tile->data.depth32[y][x] >> 24;
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_Z24X8_UNORM:
|
||||
case PIPE_FORMAT_Z24S8_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
data->bzzzz[j] = tile->data.depth32[y][x] >> 8;
|
||||
data->stencilVals[j] = tile->data.depth32[y][x] & 0xff;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert quad's float depth values to int depth values (qzzzz).
|
||||
/* If the shader has not been run, interpolate the depth values
|
||||
* ourselves.
|
||||
*/
|
||||
static void
|
||||
interpolate_quad_depth( struct quad_header *quad )
|
||||
{
|
||||
const float fx = (float) quad->input.x0;
|
||||
const float fy = (float) quad->input.y0;
|
||||
const float dzdx = quad->posCoef->dadx[2];
|
||||
const float dzdy = quad->posCoef->dady[2];
|
||||
const float z0 = quad->posCoef->a0[2] + dzdx * fx + dzdy * fy;
|
||||
|
||||
quad->output.depth[0] = z0;
|
||||
quad->output.depth[1] = z0 + dzdx;
|
||||
quad->output.depth[2] = z0 + dzdy;
|
||||
quad->output.depth[3] = z0 + dzdx + dzdy;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
convert_quad_depth( struct depth_data *data,
|
||||
const struct quad_header *quad )
|
||||
{
|
||||
unsigned j;
|
||||
|
||||
/* Convert quad's float depth values to int depth values (qzzzz).
|
||||
* If the Z buffer stores integer values, we _have_ to do the depth
|
||||
* compares with integers (not floats). Otherwise, the float->int->float
|
||||
* conversion of Z values (which isn't an identity function) will cause
|
||||
* Z-fighting errors.
|
||||
*
|
||||
* Also, get the zbuffer values (bzzzz) from the cached tile.
|
||||
*/
|
||||
switch (format) {
|
||||
switch (data->format) {
|
||||
case PIPE_FORMAT_Z16_UNORM:
|
||||
{
|
||||
float scale = 65535.0;
|
||||
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
|
||||
}
|
||||
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
bzzzz[j] = tile->data.depth16[y][x];
|
||||
data->qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -94,53 +142,286 @@ lp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
|
|||
double scale = (double) (uint) ~0UL;
|
||||
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
|
||||
}
|
||||
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
bzzzz[j] = tile->data.depth32[y][x];
|
||||
data->qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_X8Z24_UNORM:
|
||||
/* fall-through */
|
||||
case PIPE_FORMAT_S8Z24_UNORM:
|
||||
{
|
||||
float scale = (float) ((1 << 24) - 1);
|
||||
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
|
||||
}
|
||||
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
bzzzz[j] = tile->data.depth32[y][x] & 0xffffff;
|
||||
data->qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_Z24X8_UNORM:
|
||||
/* fall-through */
|
||||
case PIPE_FORMAT_Z24S8_UNORM:
|
||||
{
|
||||
float scale = (float) ((1 << 24) - 1);
|
||||
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
|
||||
}
|
||||
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
bzzzz[j] = tile->data.depth32[y][x] >> 8;
|
||||
data->qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
write_depth_stencil_values( struct depth_data *data,
|
||||
struct quad_header *quad )
|
||||
{
|
||||
struct llvmpipe_cached_tile *tile = data->tile;
|
||||
unsigned j;
|
||||
|
||||
/* put updated Z values back into cached tile */
|
||||
switch (data->format) {
|
||||
case PIPE_FORMAT_Z16_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
tile->data.depth16[y][x] = (ushort) data->bzzzz[j];
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_X8Z24_UNORM:
|
||||
case PIPE_FORMAT_Z32_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
tile->data.depth32[y][x] = data->bzzzz[j];
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_S8Z24_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
tile->data.depth32[y][x] = (data->stencilVals[j] << 24) | data->bzzzz[j];
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_Z24S8_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
tile->data.depth32[y][x] = (data->bzzzz[j] << 8) | data->stencilVals[j];
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_Z24X8_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
tile->data.depth32[y][x] = data->bzzzz[j] << 8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** Only 8-bit stencil supported */
|
||||
#define STENCIL_MAX 0xff
|
||||
|
||||
|
||||
/**
|
||||
* Do the basic stencil test (compare stencil buffer values against the
|
||||
* reference value.
|
||||
*
|
||||
* \param data->stencilVals the stencil values from the stencil buffer
|
||||
* \param func the stencil func (PIPE_FUNC_x)
|
||||
* \param ref the stencil reference value
|
||||
* \param valMask the stencil value mask indicating which bits of the stencil
|
||||
* values and ref value are to be used.
|
||||
* \return mask indicating which pixels passed the stencil test
|
||||
*/
|
||||
static unsigned
|
||||
do_stencil_test(struct depth_data *data,
|
||||
unsigned func,
|
||||
unsigned ref, unsigned valMask)
|
||||
{
|
||||
unsigned passMask = 0x0;
|
||||
unsigned j;
|
||||
|
||||
ref &= valMask;
|
||||
|
||||
switch (func) {
|
||||
case PIPE_FUNC_NEVER:
|
||||
/* passMask = 0x0 */
|
||||
break;
|
||||
case PIPE_FUNC_LESS:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (ref < (data->stencilVals[j] & valMask)) {
|
||||
passMask |= (1 << j);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FUNC_EQUAL:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (ref == (data->stencilVals[j] & valMask)) {
|
||||
passMask |= (1 << j);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FUNC_LEQUAL:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (ref <= (data->stencilVals[j] & valMask)) {
|
||||
passMask |= (1 << j);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FUNC_GREATER:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (ref > (data->stencilVals[j] & valMask)) {
|
||||
passMask |= (1 << j);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FUNC_NOTEQUAL:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (ref != (data->stencilVals[j] & valMask)) {
|
||||
passMask |= (1 << j);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FUNC_GEQUAL:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (ref >= (data->stencilVals[j] & valMask)) {
|
||||
passMask |= (1 << j);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FUNC_ALWAYS:
|
||||
passMask = MASK_ALL;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return passMask;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Apply the stencil operator to stencil values.
|
||||
*
|
||||
* \param data->stencilVals the stencil buffer values (read and written)
|
||||
* \param mask indicates which pixels to update
|
||||
* \param op the stencil operator (PIPE_STENCIL_OP_x)
|
||||
* \param ref the stencil reference value
|
||||
* \param wrtMask writemask controlling which bits are changed in the
|
||||
* stencil values
|
||||
*/
|
||||
static void
|
||||
apply_stencil_op(struct depth_data *data,
|
||||
unsigned mask, unsigned op, ubyte ref, ubyte wrtMask)
|
||||
{
|
||||
unsigned j;
|
||||
ubyte newstencil[QUAD_SIZE];
|
||||
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
newstencil[j] = data->stencilVals[j];
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
case PIPE_STENCIL_OP_KEEP:
|
||||
/* no-op */
|
||||
break;
|
||||
case PIPE_STENCIL_OP_ZERO:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (mask & (1 << j)) {
|
||||
newstencil[j] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_STENCIL_OP_REPLACE:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (mask & (1 << j)) {
|
||||
newstencil[j] = ref;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_STENCIL_OP_INCR:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (mask & (1 << j)) {
|
||||
if (data->stencilVals[j] < STENCIL_MAX) {
|
||||
newstencil[j] = data->stencilVals[j] + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_STENCIL_OP_DECR:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (mask & (1 << j)) {
|
||||
if (data->stencilVals[j] > 0) {
|
||||
newstencil[j] = data->stencilVals[j] - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_STENCIL_OP_INCR_WRAP:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (mask & (1 << j)) {
|
||||
newstencil[j] = data->stencilVals[j] + 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_STENCIL_OP_DECR_WRAP:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (mask & (1 << j)) {
|
||||
newstencil[j] = data->stencilVals[j] - 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_STENCIL_OP_INVERT:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (mask & (1 << j)) {
|
||||
newstencil[j] = ~data->stencilVals[j];
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* update the stencil values
|
||||
*/
|
||||
if (wrtMask != STENCIL_MAX) {
|
||||
/* apply bit-wise stencil buffer writemask */
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
data->stencilVals[j] = (wrtMask & newstencil[j]) | (~wrtMask & data->stencilVals[j]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
data->stencilVals[j] = newstencil[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* To increase efficiency, we should probably have multiple versions
|
||||
* of this function that are specifically for Z16, Z32 and FP Z buffers.
|
||||
* Try to effectively do that with codegen...
|
||||
*/
|
||||
|
||||
static boolean
|
||||
depth_test_quad(struct quad_stage *qs,
|
||||
struct depth_data *data,
|
||||
struct quad_header *quad)
|
||||
{
|
||||
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
|
||||
unsigned zmask = 0;
|
||||
unsigned j;
|
||||
|
||||
switch (llvmpipe->depth_stencil->depth.func) {
|
||||
case PIPE_FUNC_NEVER:
|
||||
|
|
@ -151,37 +432,37 @@ lp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
|
|||
* Like this: quad->mask &= (quad->outputs.depth < zzzz);
|
||||
*/
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (qzzzz[j] < bzzzz[j])
|
||||
if (data->qzzzz[j] < data->bzzzz[j])
|
||||
zmask |= 1 << j;
|
||||
}
|
||||
break;
|
||||
case PIPE_FUNC_EQUAL:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (qzzzz[j] == bzzzz[j])
|
||||
if (data->qzzzz[j] == data->bzzzz[j])
|
||||
zmask |= 1 << j;
|
||||
}
|
||||
break;
|
||||
case PIPE_FUNC_LEQUAL:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (qzzzz[j] <= bzzzz[j])
|
||||
if (data->qzzzz[j] <= data->bzzzz[j])
|
||||
zmask |= (1 << j);
|
||||
}
|
||||
break;
|
||||
case PIPE_FUNC_GREATER:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (qzzzz[j] > bzzzz[j])
|
||||
if (data->qzzzz[j] > data->bzzzz[j])
|
||||
zmask |= (1 << j);
|
||||
}
|
||||
break;
|
||||
case PIPE_FUNC_NOTEQUAL:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (qzzzz[j] != bzzzz[j])
|
||||
if (data->qzzzz[j] != data->bzzzz[j])
|
||||
zmask |= (1 << j);
|
||||
}
|
||||
break;
|
||||
case PIPE_FUNC_GEQUAL:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (qzzzz[j] >= bzzzz[j])
|
||||
if (data->qzzzz[j] >= data->bzzzz[j])
|
||||
zmask |= (1 << j);
|
||||
}
|
||||
break;
|
||||
|
|
@ -196,62 +477,15 @@ lp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
|
|||
if (quad->inout.mask == 0)
|
||||
return FALSE;
|
||||
|
||||
/* Update our internal copy only if writemask set. Even if
|
||||
* depth.writemask is FALSE, may still need to write out buffer
|
||||
* data due to stencil changes.
|
||||
*/
|
||||
if (llvmpipe->depth_stencil->depth.writemask) {
|
||||
|
||||
/* This is also efficient with sse / spe instructions:
|
||||
*/
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (quad->inout.mask & (1 << j)) {
|
||||
bzzzz[j] = qzzzz[j];
|
||||
}
|
||||
}
|
||||
|
||||
/* put updated Z values back into cached tile */
|
||||
switch (format) {
|
||||
case PIPE_FORMAT_Z16_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
tile->data.depth16[y][x] = (ushort) bzzzz[j];
|
||||
if (quad->inout.mask & (1 << j)) {
|
||||
data->bzzzz[j] = data->qzzzz[j];
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_X8Z24_UNORM:
|
||||
/* fall-through */
|
||||
/* (yes, this falls through to a different case than above) */
|
||||
case PIPE_FORMAT_Z32_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
tile->data.depth32[y][x] = bzzzz[j];
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_S8Z24_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
uint s8z24 = tile->data.depth32[y][x];
|
||||
s8z24 = (s8z24 & 0xff000000) | bzzzz[j];
|
||||
tile->data.depth32[y][x] = s8z24;
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_Z24S8_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
uint z24s8 = tile->data.depth32[y][x];
|
||||
z24s8 = (z24s8 & 0xff) | (bzzzz[j] << 8);
|
||||
tile->data.depth32[y][x] = z24s8;
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_Z24X8_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
tile->data.depth32[y][x] = bzzzz[j] << 8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -259,20 +493,215 @@ lp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Do stencil (and depth) testing. Stenciling depends on the outcome of
|
||||
* depth testing.
|
||||
*/
|
||||
static boolean
|
||||
depth_stencil_test_quad(struct quad_stage *qs,
|
||||
struct depth_data *data,
|
||||
struct quad_header *quad)
|
||||
{
|
||||
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
|
||||
unsigned func, zFailOp, zPassOp, failOp;
|
||||
ubyte ref, wrtMask, valMask;
|
||||
uint face = quad->input.facing;
|
||||
|
||||
if (!llvmpipe->depth_stencil->stencil[1].enabled) {
|
||||
/* single-sided stencil test, use front (face=0) state */
|
||||
face = 0;
|
||||
}
|
||||
|
||||
/* choose front or back face function, operator, etc */
|
||||
/* XXX we could do these initializations once per primitive */
|
||||
func = llvmpipe->depth_stencil->stencil[face].func;
|
||||
failOp = llvmpipe->depth_stencil->stencil[face].fail_op;
|
||||
zFailOp = llvmpipe->depth_stencil->stencil[face].zfail_op;
|
||||
zPassOp = llvmpipe->depth_stencil->stencil[face].zpass_op;
|
||||
ref = llvmpipe->depth_stencil->stencil[face].ref_value;
|
||||
wrtMask = llvmpipe->depth_stencil->stencil[face].writemask;
|
||||
valMask = llvmpipe->depth_stencil->stencil[face].valuemask;
|
||||
|
||||
|
||||
/* do the stencil test first */
|
||||
{
|
||||
unsigned passMask, failMask;
|
||||
passMask = do_stencil_test(data, func, ref, valMask);
|
||||
failMask = quad->inout.mask & ~passMask;
|
||||
quad->inout.mask &= passMask;
|
||||
|
||||
if (failOp != PIPE_STENCIL_OP_KEEP) {
|
||||
apply_stencil_op(data, failMask, failOp, ref, wrtMask);
|
||||
}
|
||||
}
|
||||
|
||||
if (quad->inout.mask) {
|
||||
/* now the pixels that passed the stencil test are depth tested */
|
||||
if (llvmpipe->depth_stencil->depth.enabled) {
|
||||
const unsigned origMask = quad->inout.mask;
|
||||
|
||||
depth_test_quad(qs, data, quad); /* quad->mask is updated */
|
||||
|
||||
/* update stencil buffer values according to z pass/fail result */
|
||||
if (zFailOp != PIPE_STENCIL_OP_KEEP) {
|
||||
const unsigned failMask = origMask & ~quad->inout.mask;
|
||||
apply_stencil_op(data, failMask, zFailOp, ref, wrtMask);
|
||||
}
|
||||
|
||||
if (zPassOp != PIPE_STENCIL_OP_KEEP) {
|
||||
const unsigned passMask = origMask & quad->inout.mask;
|
||||
apply_stencil_op(data, passMask, zPassOp, ref, wrtMask);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* no depth test, apply Zpass operator to stencil buffer values */
|
||||
apply_stencil_op(data, quad->inout.mask, zPassOp, ref, wrtMask);
|
||||
}
|
||||
}
|
||||
|
||||
return quad->inout.mask != 0;
|
||||
}
|
||||
|
||||
|
||||
#define ALPHATEST( FUNC, COMP ) \
|
||||
static int \
|
||||
alpha_test_quads_##FUNC( struct quad_stage *qs, \
|
||||
struct quad_header *quads[], \
|
||||
unsigned nr ) \
|
||||
{ \
|
||||
const float ref = qs->llvmpipe->depth_stencil->alpha.ref_value; \
|
||||
const uint cbuf = 0; /* only output[0].alpha is tested */ \
|
||||
unsigned pass_nr = 0; \
|
||||
unsigned i; \
|
||||
\
|
||||
for (i = 0; i < nr; i++) { \
|
||||
const float *aaaa = quads[i]->output.color[cbuf][3]; \
|
||||
unsigned passMask = 0; \
|
||||
\
|
||||
if (aaaa[0] COMP ref) passMask |= (1 << 0); \
|
||||
if (aaaa[1] COMP ref) passMask |= (1 << 1); \
|
||||
if (aaaa[2] COMP ref) passMask |= (1 << 2); \
|
||||
if (aaaa[3] COMP ref) passMask |= (1 << 3); \
|
||||
\
|
||||
quads[i]->inout.mask &= passMask; \
|
||||
\
|
||||
if (quads[i]->inout.mask) \
|
||||
quads[pass_nr++] = quads[i]; \
|
||||
} \
|
||||
\
|
||||
return pass_nr; \
|
||||
}
|
||||
|
||||
|
||||
ALPHATEST( LESS, < )
|
||||
ALPHATEST( EQUAL, == )
|
||||
ALPHATEST( LEQUAL, <= )
|
||||
ALPHATEST( GREATER, > )
|
||||
ALPHATEST( NOTEQUAL, != )
|
||||
ALPHATEST( GEQUAL, >= )
|
||||
|
||||
|
||||
/* XXX: Incorporate into shader using KILP.
|
||||
*/
|
||||
static int
|
||||
alpha_test_quads(struct quad_stage *qs,
|
||||
struct quad_header *quads[],
|
||||
unsigned nr)
|
||||
{
|
||||
switch (qs->llvmpipe->depth_stencil->alpha.func) {
|
||||
case PIPE_FUNC_LESS:
|
||||
return alpha_test_quads_LESS( qs, quads, nr );
|
||||
case PIPE_FUNC_EQUAL:
|
||||
return alpha_test_quads_EQUAL( qs, quads, nr );
|
||||
break;
|
||||
case PIPE_FUNC_LEQUAL:
|
||||
return alpha_test_quads_LEQUAL( qs, quads, nr );
|
||||
case PIPE_FUNC_GREATER:
|
||||
return alpha_test_quads_GREATER( qs, quads, nr );
|
||||
case PIPE_FUNC_NOTEQUAL:
|
||||
return alpha_test_quads_NOTEQUAL( qs, quads, nr );
|
||||
case PIPE_FUNC_GEQUAL:
|
||||
return alpha_test_quads_GEQUAL( qs, quads, nr );
|
||||
case PIPE_FUNC_ALWAYS:
|
||||
return nr;
|
||||
case PIPE_FUNC_NEVER:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned mask_count[0x8] =
|
||||
{
|
||||
0, /* 0x0 */
|
||||
1, /* 0x1 */
|
||||
1, /* 0x2 */
|
||||
2, /* 0x3 */
|
||||
1, /* 0x4 */
|
||||
2, /* 0x5 */
|
||||
2, /* 0x6 */
|
||||
3, /* 0x7 */
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void
|
||||
depth_test_quads(struct quad_stage *qs,
|
||||
struct quad_header *quads[],
|
||||
unsigned nr)
|
||||
{
|
||||
unsigned i, pass = 0;
|
||||
const struct lp_fragment_shader *fs = qs->llvmpipe->fs;
|
||||
boolean interp_depth = !fs->info.writes_z;
|
||||
struct depth_data data;
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
if (lp_depth_test_quad(qs, quads[i]))
|
||||
quads[pass++] = quads[i];
|
||||
|
||||
if (qs->llvmpipe->depth_stencil->alpha.enabled) {
|
||||
nr = alpha_test_quads(qs, quads, nr);
|
||||
}
|
||||
|
||||
if (pass)
|
||||
qs->next->run(qs->next, quads, pass);
|
||||
|
||||
if (qs->llvmpipe->framebuffer.zsbuf &&
|
||||
(qs->llvmpipe->depth_stencil->depth.enabled ||
|
||||
qs->llvmpipe->depth_stencil->stencil[0].enabled)) {
|
||||
|
||||
data.ps = qs->llvmpipe->framebuffer.zsbuf;
|
||||
data.format = data.ps->format;
|
||||
data.tile = lp_get_cached_tile(qs->llvmpipe->zsbuf_cache,
|
||||
quads[0]->input.x0,
|
||||
quads[0]->input.y0);
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
get_depth_stencil_values(&data, quads[i]);
|
||||
|
||||
if (qs->llvmpipe->depth_stencil->depth.enabled) {
|
||||
if (interp_depth)
|
||||
interpolate_quad_depth(quads[i]);
|
||||
|
||||
convert_quad_depth(&data, quads[i]);
|
||||
}
|
||||
|
||||
if (qs->llvmpipe->depth_stencil->stencil[0].enabled) {
|
||||
if (!depth_stencil_test_quad(qs, &data, quads[i]))
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
if (!depth_test_quad(qs, &data, quads[i]))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (qs->llvmpipe->depth_stencil->stencil[0].enabled ||
|
||||
qs->llvmpipe->depth_stencil->depth.writemask)
|
||||
write_depth_stencil_values(&data, quads[i]);
|
||||
|
||||
qs->llvmpipe->occlusion_count += mask_count[quads[i]->inout.mask];
|
||||
quads[pass++] = quads[i];
|
||||
}
|
||||
|
||||
nr = pass;
|
||||
}
|
||||
|
||||
if (nr)
|
||||
qs->next->run(qs->next, quads, nr);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,94 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* \brief Quad early-z testing
|
||||
*/
|
||||
|
||||
#include "pipe/p_defines.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "lp_quad.h"
|
||||
#include "lp_quad_pipe.h"
|
||||
|
||||
|
||||
/**
|
||||
* All this stage does is compute the quad's Z values (which is normally
|
||||
* done by the shading stage).
|
||||
* The next stage will do the actual depth test.
|
||||
*/
|
||||
static void
|
||||
earlyz_quad(
|
||||
struct quad_stage *qs,
|
||||
struct quad_header *quads[],
|
||||
unsigned nr )
|
||||
{
|
||||
const float a0z = quads[0]->posCoef->a0[2];
|
||||
const float dzdx = quads[0]->posCoef->dadx[2];
|
||||
const float dzdy = quads[0]->posCoef->dady[2];
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
const float fx = (float) quads[i]->input.x0;
|
||||
const float fy = (float) quads[i]->input.y0;
|
||||
const float z0 = a0z + dzdx * fx + dzdy * fy;
|
||||
|
||||
quads[i]->output.depth[0] = z0;
|
||||
quads[i]->output.depth[1] = z0 + dzdx;
|
||||
quads[i]->output.depth[2] = z0 + dzdy;
|
||||
quads[i]->output.depth[3] = z0 + dzdx + dzdy;
|
||||
}
|
||||
|
||||
qs->next->run( qs->next, quads, nr );
|
||||
}
|
||||
|
||||
static void
|
||||
earlyz_begin(
|
||||
struct quad_stage *qs )
|
||||
{
|
||||
qs->next->begin( qs->next );
|
||||
}
|
||||
|
||||
static void
|
||||
earlyz_destroy(
|
||||
struct quad_stage *qs )
|
||||
{
|
||||
FREE( qs );
|
||||
}
|
||||
|
||||
struct quad_stage *
|
||||
lp_quad_earlyz_stage(
|
||||
struct llvmpipe_context *llvmpipe )
|
||||
{
|
||||
struct quad_stage *stage = CALLOC_STRUCT( quad_stage );
|
||||
|
||||
stage->llvmpipe = llvmpipe;
|
||||
stage->begin = earlyz_begin;
|
||||
stage->run = earlyz_quad;
|
||||
stage->destroy = earlyz_destroy;
|
||||
|
||||
return stage;
|
||||
}
|
||||
|
|
@ -111,24 +111,31 @@ shade_quad(struct quad_stage *qs, struct quad_header *quad)
|
|||
}
|
||||
}
|
||||
|
||||
if (!z_written) {
|
||||
/* compute Z values now, as in the quad earlyz stage */
|
||||
/* XXX we should really only do this if the earlyz stage is not used */
|
||||
const float fx = (float) quad->input.x0;
|
||||
const float fy = (float) quad->input.y0;
|
||||
const float dzdx = quad->posCoef->dadx[2];
|
||||
const float dzdy = quad->posCoef->dady[2];
|
||||
const float z0 = quad->posCoef->a0[2] + dzdx * fx + dzdy * fy;
|
||||
|
||||
quad->output.depth[0] = z0;
|
||||
quad->output.depth[1] = z0 + dzdx;
|
||||
quad->output.depth[2] = z0 + dzdy;
|
||||
quad->output.depth[3] = z0 + dzdx + dzdy;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
coverage_quad(struct quad_stage *qs, struct quad_header *quad)
|
||||
{
|
||||
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
|
||||
uint cbuf;
|
||||
|
||||
/* loop over colorbuffer outputs */
|
||||
for (cbuf = 0; cbuf < llvmpipe->framebuffer.nr_cbufs; cbuf++) {
|
||||
float (*quadColor)[4] = quad->output.color[cbuf];
|
||||
unsigned j;
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
assert(quad->input.coverage[j] >= 0.0);
|
||||
assert(quad->input.coverage[j] <= 1.0);
|
||||
quadColor[3][j] *= quad->input.coverage[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
shade_quads(struct quad_stage *qs,
|
||||
struct quad_header *quads[],
|
||||
|
|
@ -144,8 +151,13 @@ shade_quads(struct quad_stage *qs,
|
|||
machine->InterpCoefs = quads[0]->coef;
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
if (shade_quad(qs, quads[i]))
|
||||
quads[pass++] = quads[i];
|
||||
if (!shade_quad(qs, quads[i]))
|
||||
continue;
|
||||
|
||||
if (/*do_coverage*/ 0)
|
||||
coverage_quad( qs, quads[i] );
|
||||
|
||||
quads[pass++] = quads[i];
|
||||
}
|
||||
|
||||
if (pass)
|
||||
|
|
|
|||
|
|
@ -1,87 +0,0 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* \brief Quad occlusion counter stage
|
||||
* \author Brian Paul
|
||||
*/
|
||||
|
||||
|
||||
#include "pipe/p_defines.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "lp_context.h"
|
||||
#include "lp_quad.h"
|
||||
#include "lp_surface.h"
|
||||
#include "lp_quad_pipe.h"
|
||||
|
||||
static unsigned count_bits( unsigned val )
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; val ; val >>= 1)
|
||||
i += (val & 1);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void
|
||||
occlusion_count_quads(struct quad_stage *qs, struct quad_header *quads[], unsigned nr)
|
||||
{
|
||||
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < nr; i++)
|
||||
llvmpipe->occlusion_count += count_bits(quads[i]->inout.mask);
|
||||
|
||||
qs->next->run(qs->next, quads, nr);
|
||||
}
|
||||
|
||||
|
||||
static void occlusion_begin(struct quad_stage *qs)
|
||||
{
|
||||
qs->next->begin(qs->next);
|
||||
}
|
||||
|
||||
|
||||
static void occlusion_destroy(struct quad_stage *qs)
|
||||
{
|
||||
FREE( qs );
|
||||
}
|
||||
|
||||
|
||||
struct quad_stage *lp_quad_occlusion_stage( struct llvmpipe_context *llvmpipe )
|
||||
{
|
||||
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
|
||||
|
||||
stage->llvmpipe = llvmpipe;
|
||||
stage->begin = occlusion_begin;
|
||||
stage->run = occlusion_count_quads;
|
||||
stage->destroy = occlusion_destroy;
|
||||
|
||||
return stage;
|
||||
}
|
||||
|
|
@ -38,18 +38,6 @@ lp_push_quad_first( struct llvmpipe_context *lp,
|
|||
lp->quad.first = quad;
|
||||
}
|
||||
|
||||
static void
|
||||
lp_build_depth_stencil( struct llvmpipe_context *lp )
|
||||
{
|
||||
if (lp->depth_stencil->stencil[0].enabled ||
|
||||
lp->depth_stencil->stencil[1].enabled) {
|
||||
lp_push_quad_first( lp, lp->quad.stencil_test );
|
||||
}
|
||||
else if (lp->depth_stencil->depth.enabled &&
|
||||
lp->framebuffer.zsbuf) {
|
||||
lp_push_quad_first( lp, lp->quad.depth_test );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lp_build_quad_pipeline(struct llvmpipe_context *lp)
|
||||
|
|
@ -61,37 +49,15 @@ lp_build_quad_pipeline(struct llvmpipe_context *lp)
|
|||
!lp->fs->info.uses_kill &&
|
||||
!lp->fs->info.writes_z;
|
||||
|
||||
/* build up the pipeline in reverse order... */
|
||||
|
||||
/* Color combine
|
||||
*/
|
||||
lp->quad.first = lp->quad.blend;
|
||||
|
||||
/* Shade/Depth/Stencil/Alpha
|
||||
*/
|
||||
if ((lp->rasterizer->poly_smooth && lp->reduced_prim == PIPE_PRIM_TRIANGLES) ||
|
||||
(lp->rasterizer->line_smooth && lp->reduced_prim == PIPE_PRIM_LINES) ||
|
||||
(lp->rasterizer->point_smooth && lp->reduced_prim == PIPE_PRIM_POINTS)) {
|
||||
lp_push_quad_first( lp, lp->quad.coverage );
|
||||
}
|
||||
|
||||
if (lp->active_query_count) {
|
||||
lp_push_quad_first( lp, lp->quad.occlusion );
|
||||
}
|
||||
|
||||
if (!early_depth_test) {
|
||||
lp_build_depth_stencil( lp );
|
||||
}
|
||||
|
||||
if (lp->depth_stencil->alpha.enabled) {
|
||||
lp_push_quad_first( lp, lp->quad.alpha_test );
|
||||
}
|
||||
|
||||
lp_push_quad_first( lp, lp->quad.shade );
|
||||
|
||||
if (early_depth_test) {
|
||||
lp_build_depth_stencil( lp );
|
||||
lp_push_quad_first( lp, lp->quad.earlyz );
|
||||
lp_push_quad_first( lp, lp->quad.shade );
|
||||
lp_push_quad_first( lp, lp->quad.depth_test );
|
||||
}
|
||||
else {
|
||||
lp_push_quad_first( lp, lp->quad.depth_test );
|
||||
lp_push_quad_first( lp, lp->quad.shade );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,4 @@ struct quad_stage *lp_quad_output_stage( struct llvmpipe_context *llvmpipe );
|
|||
|
||||
void lp_build_quad_pipeline(struct llvmpipe_context *lp);
|
||||
|
||||
boolean lp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad);
|
||||
|
||||
#endif /* LP_QUAD_PIPE_H */
|
||||
|
|
|
|||
|
|
@ -1,363 +0,0 @@
|
|||
|
||||
/**
|
||||
* \brief Quad stencil testing
|
||||
*/
|
||||
|
||||
|
||||
#include "lp_context.h"
|
||||
#include "lp_quad.h"
|
||||
#include "lp_surface.h"
|
||||
#include "lp_tile_cache.h"
|
||||
#include "lp_quad_pipe.h"
|
||||
#include "pipe/p_defines.h"
|
||||
#include "util/u_memory.h"
|
||||
|
||||
|
||||
/** Only 8-bit stencil supported */
|
||||
#define STENCIL_MAX 0xff
|
||||
|
||||
|
||||
/**
|
||||
* Do the basic stencil test (compare stencil buffer values against the
|
||||
* reference value.
|
||||
*
|
||||
* \param stencilVals the stencil values from the stencil buffer
|
||||
* \param func the stencil func (PIPE_FUNC_x)
|
||||
* \param ref the stencil reference value
|
||||
* \param valMask the stencil value mask indicating which bits of the stencil
|
||||
* values and ref value are to be used.
|
||||
* \return mask indicating which pixels passed the stencil test
|
||||
*/
|
||||
static unsigned
|
||||
do_stencil_test(const ubyte stencilVals[QUAD_SIZE], unsigned func,
|
||||
unsigned ref, unsigned valMask)
|
||||
{
|
||||
unsigned passMask = 0x0;
|
||||
unsigned j;
|
||||
|
||||
ref &= valMask;
|
||||
|
||||
switch (func) {
|
||||
case PIPE_FUNC_NEVER:
|
||||
/* passMask = 0x0 */
|
||||
break;
|
||||
case PIPE_FUNC_LESS:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (ref < (stencilVals[j] & valMask)) {
|
||||
passMask |= (1 << j);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FUNC_EQUAL:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (ref == (stencilVals[j] & valMask)) {
|
||||
passMask |= (1 << j);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FUNC_LEQUAL:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (ref <= (stencilVals[j] & valMask)) {
|
||||
passMask |= (1 << j);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FUNC_GREATER:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (ref > (stencilVals[j] & valMask)) {
|
||||
passMask |= (1 << j);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FUNC_NOTEQUAL:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (ref != (stencilVals[j] & valMask)) {
|
||||
passMask |= (1 << j);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FUNC_GEQUAL:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (ref >= (stencilVals[j] & valMask)) {
|
||||
passMask |= (1 << j);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_FUNC_ALWAYS:
|
||||
passMask = MASK_ALL;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return passMask;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Apply the stencil operator to stencil values.
|
||||
*
|
||||
* \param stencilVals the stencil buffer values (read and written)
|
||||
* \param mask indicates which pixels to update
|
||||
* \param op the stencil operator (PIPE_STENCIL_OP_x)
|
||||
* \param ref the stencil reference value
|
||||
* \param wrtMask writemask controlling which bits are changed in the
|
||||
* stencil values
|
||||
*/
|
||||
static void
|
||||
apply_stencil_op(ubyte stencilVals[QUAD_SIZE],
|
||||
unsigned mask, unsigned op, ubyte ref, ubyte wrtMask)
|
||||
{
|
||||
unsigned j;
|
||||
ubyte newstencil[QUAD_SIZE];
|
||||
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
newstencil[j] = stencilVals[j];
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
case PIPE_STENCIL_OP_KEEP:
|
||||
/* no-op */
|
||||
break;
|
||||
case PIPE_STENCIL_OP_ZERO:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (mask & (1 << j)) {
|
||||
newstencil[j] = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_STENCIL_OP_REPLACE:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (mask & (1 << j)) {
|
||||
newstencil[j] = ref;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_STENCIL_OP_INCR:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (mask & (1 << j)) {
|
||||
if (stencilVals[j] < STENCIL_MAX) {
|
||||
newstencil[j] = stencilVals[j] + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_STENCIL_OP_DECR:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (mask & (1 << j)) {
|
||||
if (stencilVals[j] > 0) {
|
||||
newstencil[j] = stencilVals[j] - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_STENCIL_OP_INCR_WRAP:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (mask & (1 << j)) {
|
||||
newstencil[j] = stencilVals[j] + 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_STENCIL_OP_DECR_WRAP:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (mask & (1 << j)) {
|
||||
newstencil[j] = stencilVals[j] - 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PIPE_STENCIL_OP_INVERT:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
if (mask & (1 << j)) {
|
||||
newstencil[j] = ~stencilVals[j];
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* update the stencil values
|
||||
*/
|
||||
if (wrtMask != STENCIL_MAX) {
|
||||
/* apply bit-wise stencil buffer writemask */
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
stencilVals[j] = (wrtMask & newstencil[j]) | (~wrtMask & stencilVals[j]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
stencilVals[j] = newstencil[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do stencil (and depth) testing. Stenciling depends on the outcome of
|
||||
* depth testing.
|
||||
*/
|
||||
static void
|
||||
stencil_test_quad(struct quad_stage *qs, struct quad_header *quads[],
|
||||
unsigned nr)
|
||||
{
|
||||
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
|
||||
struct pipe_surface *ps = llvmpipe->framebuffer.zsbuf;
|
||||
unsigned func, zFailOp, zPassOp, failOp;
|
||||
ubyte ref, wrtMask, valMask;
|
||||
ubyte stencilVals[QUAD_SIZE];
|
||||
struct llvmpipe_cached_tile *tile
|
||||
= lp_get_cached_tile(llvmpipe->zsbuf_cache,
|
||||
quads[0]->input.x0,
|
||||
quads[0]->input.y0);
|
||||
uint face = quads[0]->input.facing;
|
||||
uint pass = 0;
|
||||
uint j, q;
|
||||
|
||||
if (!llvmpipe->depth_stencil->stencil[1].enabled) {
|
||||
/* single-sided stencil test, use front (face=0) state */
|
||||
face = 0;
|
||||
}
|
||||
|
||||
/* choose front or back face function, operator, etc */
|
||||
/* XXX we could do these initializations once per primitive */
|
||||
func = llvmpipe->depth_stencil->stencil[face].func;
|
||||
failOp = llvmpipe->depth_stencil->stencil[face].fail_op;
|
||||
zFailOp = llvmpipe->depth_stencil->stencil[face].zfail_op;
|
||||
zPassOp = llvmpipe->depth_stencil->stencil[face].zpass_op;
|
||||
ref = llvmpipe->depth_stencil->stencil[face].ref_value;
|
||||
wrtMask = llvmpipe->depth_stencil->stencil[face].writemask;
|
||||
valMask = llvmpipe->depth_stencil->stencil[face].valuemask;
|
||||
|
||||
assert(ps); /* shouldn't get here if there's no stencil buffer */
|
||||
|
||||
for (q = 0; q < nr; q++) {
|
||||
struct quad_header *quad = quads[q];
|
||||
|
||||
/* get stencil values from cached tile */
|
||||
switch (ps->format) {
|
||||
case PIPE_FORMAT_S8Z24_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
stencilVals[j] = tile->data.depth32[y][x] >> 24;
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_Z24S8_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
stencilVals[j] = tile->data.depth32[y][x] & 0xff;
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_S8_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
stencilVals[j] = tile->data.stencil8[y][x];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* do the stencil test first */
|
||||
{
|
||||
unsigned passMask, failMask;
|
||||
passMask = do_stencil_test(stencilVals, func, ref, valMask);
|
||||
failMask = quad->inout.mask & ~passMask;
|
||||
quad->inout.mask &= passMask;
|
||||
|
||||
if (failOp != PIPE_STENCIL_OP_KEEP) {
|
||||
apply_stencil_op(stencilVals, failMask, failOp, ref, wrtMask);
|
||||
}
|
||||
}
|
||||
|
||||
if (quad->inout.mask) {
|
||||
/* now the pixels that passed the stencil test are depth tested */
|
||||
if (llvmpipe->depth_stencil->depth.enabled) {
|
||||
const unsigned origMask = quad->inout.mask;
|
||||
|
||||
lp_depth_test_quad(qs, quad); /* quad->mask is updated */
|
||||
|
||||
/* update stencil buffer values according to z pass/fail result */
|
||||
if (zFailOp != PIPE_STENCIL_OP_KEEP) {
|
||||
const unsigned failMask = origMask & ~quad->inout.mask;
|
||||
apply_stencil_op(stencilVals, failMask, zFailOp, ref, wrtMask);
|
||||
}
|
||||
|
||||
if (zPassOp != PIPE_STENCIL_OP_KEEP) {
|
||||
const unsigned passMask = origMask & quad->inout.mask;
|
||||
apply_stencil_op(stencilVals, passMask, zPassOp, ref, wrtMask);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* no depth test, apply Zpass operator to stencil buffer values */
|
||||
apply_stencil_op(stencilVals, quad->inout.mask, zPassOp, ref, wrtMask);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* put new stencil values into cached tile */
|
||||
switch (ps->format) {
|
||||
case PIPE_FORMAT_S8Z24_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
uint s8z24 = tile->data.depth32[y][x];
|
||||
s8z24 = (stencilVals[j] << 24) | (s8z24 & 0xffffff);
|
||||
tile->data.depth32[y][x] = s8z24;
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_Z24S8_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
uint z24s8 = tile->data.depth32[y][x];
|
||||
z24s8 = (z24s8 & 0xffffff00) | stencilVals[j];
|
||||
tile->data.depth32[y][x] = z24s8;
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_S8_UNORM:
|
||||
for (j = 0; j < QUAD_SIZE; j++) {
|
||||
int x = quad->input.x0 % TILE_SIZE + (j & 1);
|
||||
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
|
||||
tile->data.stencil8[y][x] = stencilVals[j];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (quad->inout.mask)
|
||||
quads[pass++] = quad;
|
||||
}
|
||||
|
||||
if (pass)
|
||||
qs->next->run(qs->next, quads, pass);
|
||||
}
|
||||
|
||||
|
||||
static void stencil_begin(struct quad_stage *qs)
|
||||
{
|
||||
qs->next->begin(qs->next);
|
||||
}
|
||||
|
||||
|
||||
static void stencil_destroy(struct quad_stage *qs)
|
||||
{
|
||||
FREE( qs );
|
||||
}
|
||||
|
||||
|
||||
struct quad_stage *lp_quad_stencil_test_stage( struct llvmpipe_context *llvmpipe )
|
||||
{
|
||||
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
|
||||
|
||||
stage->llvmpipe = llvmpipe;
|
||||
stage->begin = stencil_begin;
|
||||
stage->run = stencil_test_quad;
|
||||
stage->destroy = stencil_destroy;
|
||||
|
||||
return stage;
|
||||
}
|
||||
|
|
@ -246,9 +246,7 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
|
|||
if (llvmpipe->dirty & (LP_NEW_BLEND |
|
||||
LP_NEW_DEPTH_STENCIL_ALPHA |
|
||||
LP_NEW_FRAMEBUFFER |
|
||||
LP_NEW_RASTERIZER |
|
||||
LP_NEW_FS |
|
||||
LP_NEW_QUERY))
|
||||
LP_NEW_FS))
|
||||
lp_build_quad_pipeline(llvmpipe);
|
||||
|
||||
llvmpipe->dirty = 0;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue