llvmpipe: native point rasterization
Conflicts: src/gallium/drivers/llvmpipe/lp_setup_context.h src/gallium/drivers/llvmpipe/lp_setup_line.c src/gallium/drivers/llvmpipe/lp_setup_tri.c
This commit is contained in:
committed by
Keith Whitwell
parent
3783053fa5
commit
57d84d9ca4
@@ -155,8 +155,10 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv )
|
||||
draw_install_aapoint_stage(llvmpipe->draw, &llvmpipe->pipe);
|
||||
draw_install_pstipple_stage(llvmpipe->draw, &llvmpipe->pipe);
|
||||
|
||||
/* convert points and lines into triangles: */
|
||||
draw_wide_point_threshold(llvmpipe->draw, 0.0);
|
||||
/* convert points and lines into triangles:
|
||||
* (otherwise, draw points and lines natively)
|
||||
*/
|
||||
draw_wide_point_threshold(llvmpipe->draw, 10000.0);
|
||||
draw_wide_line_threshold(llvmpipe->draw, 10000.0);
|
||||
|
||||
#if USE_DRAW_STAGE_PSTIPPLE
|
||||
|
||||
@@ -101,6 +101,9 @@ struct llvmpipe_context {
|
||||
|
||||
/** Vertex format */
|
||||
struct vertex_info vertex_info;
|
||||
|
||||
/** Which vertex shader output slot contains point size */
|
||||
int psize_slot;
|
||||
|
||||
/** Fragment shader input interpolation info */
|
||||
unsigned num_inputs;
|
||||
|
||||
@@ -494,6 +494,15 @@ lp_setup_set_line_state( struct lp_setup_context *setup,
|
||||
setup->line_width = line_width;
|
||||
}
|
||||
|
||||
void
|
||||
lp_setup_set_point_state( struct lp_setup_context *setup,
|
||||
float point_size)
|
||||
{
|
||||
LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
|
||||
|
||||
setup->point_size = point_size;
|
||||
}
|
||||
|
||||
void
|
||||
lp_setup_set_fs_inputs( struct lp_setup_context *setup,
|
||||
const struct lp_shader_input *input,
|
||||
@@ -733,6 +742,12 @@ lp_setup_update_state( struct lp_setup_context *setup )
|
||||
*/
|
||||
{
|
||||
struct llvmpipe_context *lp = llvmpipe_context(scene->pipe);
|
||||
|
||||
/* Will probably need to move this somewhere else, just need
|
||||
* to know about vertex shader point size attribute.
|
||||
*/
|
||||
setup->psize = lp->psize_slot;
|
||||
|
||||
if (lp->dirty) {
|
||||
llvmpipe_update_derived(lp);
|
||||
}
|
||||
|
||||
@@ -104,6 +104,10 @@ void
|
||||
lp_setup_set_line_state( struct lp_setup_context *setup,
|
||||
float line_width);
|
||||
|
||||
void
|
||||
lp_setup_set_point_state( struct lp_setup_context *setup,
|
||||
float point_size);
|
||||
|
||||
void
|
||||
lp_setup_set_fs_inputs( struct lp_setup_context *setup,
|
||||
const struct lp_shader_input *interp,
|
||||
|
||||
@@ -92,6 +92,8 @@ struct lp_setup_context
|
||||
unsigned cullmode;
|
||||
float pixel_offset;
|
||||
float line_width;
|
||||
float point_size;
|
||||
float psize;
|
||||
|
||||
struct pipe_framebuffer_state fb;
|
||||
struct u_rect framebuffer;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* Copyright 2010, VMware Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -18,7 +18,7 @@
|
||||
* 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
|
||||
* IN NO EVENT SHALL VMWARE 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.
|
||||
@@ -30,10 +30,229 @@
|
||||
*/
|
||||
|
||||
#include "lp_setup_context.h"
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "lp_perf.h"
|
||||
#include "lp_setup_context.h"
|
||||
#include "lp_rast.h"
|
||||
#include "lp_state_fs.h"
|
||||
|
||||
#define NUM_CHANNELS 4
|
||||
|
||||
struct point_info {
|
||||
/* x,y deltas */
|
||||
int dy01, dy12;
|
||||
int dx01, dx12;
|
||||
|
||||
const float (*v0)[4];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compute a0 for a constant-valued coefficient (GL_FLAT shading).
|
||||
*/
|
||||
static void constant_coef( struct lp_setup_context *setup,
|
||||
struct lp_rast_triangle *point,
|
||||
unsigned slot,
|
||||
const float value,
|
||||
unsigned i )
|
||||
{
|
||||
point->inputs.a0[slot][i] = value;
|
||||
point->inputs.dadx[slot][i] = 0.0f;
|
||||
point->inputs.dady[slot][i] = 0.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Special coefficient setup for gl_FragCoord.
|
||||
* X and Y are trivial
|
||||
* Z and W are copied from position_coef which should have already been computed.
|
||||
* We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
|
||||
*/
|
||||
static void
|
||||
setup_point_fragcoord_coef(struct lp_setup_context *setup,
|
||||
struct lp_rast_triangle *point,
|
||||
const struct point_info *info,
|
||||
unsigned slot,
|
||||
unsigned usage_mask)
|
||||
{
|
||||
/*X*/
|
||||
if (usage_mask & TGSI_WRITEMASK_X) {
|
||||
point->inputs.a0[slot][0] = 0.0;
|
||||
point->inputs.dadx[slot][0] = 1.0;
|
||||
point->inputs.dady[slot][0] = 0.0;
|
||||
}
|
||||
|
||||
/*Y*/
|
||||
if (usage_mask & TGSI_WRITEMASK_Y) {
|
||||
point->inputs.a0[slot][1] = 0.0;
|
||||
point->inputs.dadx[slot][1] = 0.0;
|
||||
point->inputs.dady[slot][1] = 1.0;
|
||||
}
|
||||
|
||||
/*Z*/
|
||||
if (usage_mask & TGSI_WRITEMASK_Z) {
|
||||
constant_coef(setup, point, slot, info->v0[0][2], 2);
|
||||
}
|
||||
|
||||
/*W*/
|
||||
if (usage_mask & TGSI_WRITEMASK_W) {
|
||||
constant_coef(setup, point, slot, info->v0[0][3], 3);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the point->coef[] array dadx, dady, a0 values.
|
||||
*/
|
||||
static void
|
||||
setup_point_coefficients( struct lp_setup_context *setup,
|
||||
struct lp_rast_triangle *point,
|
||||
const struct point_info *info)
|
||||
{
|
||||
unsigned fragcoord_usage_mask = TGSI_WRITEMASK_XYZ;
|
||||
unsigned slot;
|
||||
|
||||
/* setup interpolation for all the remaining attributes:
|
||||
*/
|
||||
for (slot = 0; slot < setup->fs.nr_inputs; slot++) {
|
||||
unsigned vert_attr = setup->fs.input[slot].src_index;
|
||||
unsigned usage_mask = setup->fs.input[slot].usage_mask;
|
||||
unsigned i;
|
||||
|
||||
switch (setup->fs.input[slot].interp) {
|
||||
case LP_INTERP_POSITION:
|
||||
/*
|
||||
* The generated pixel interpolators will pick up the coeffs from
|
||||
* slot 0, so all need to ensure that the usage mask is covers all
|
||||
* usages.
|
||||
*/
|
||||
fragcoord_usage_mask |= usage_mask;
|
||||
break;
|
||||
|
||||
default:
|
||||
for (i = 0; i < NUM_CHANNELS; i++) {
|
||||
if (usage_mask & (1 << i))
|
||||
constant_coef(setup, point, slot+1, info->v0[vert_attr][i], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* The internal position input is in slot zero:
|
||||
*/
|
||||
setup_point_fragcoord_coef(setup, point, info, 0,
|
||||
fragcoord_usage_mask);
|
||||
}
|
||||
|
||||
static INLINE int
|
||||
subpixel_snap(float a)
|
||||
{
|
||||
return util_iround(FIXED_ONE * a);
|
||||
}
|
||||
|
||||
|
||||
static void lp_setup_point( struct lp_setup_context *setup,
|
||||
const float (*v0)[4] )
|
||||
const float (*v0)[4] )
|
||||
{
|
||||
/* x/y positions in fixed point */
|
||||
const int sizeAttr = setup->psize;
|
||||
const float size
|
||||
= sizeAttr > 0 ? v0[sizeAttr][0]
|
||||
: setup->point_size;
|
||||
const float half_width = 0.5F * size;
|
||||
|
||||
const int x0 = subpixel_snap(v0[0][0] - half_width - setup->pixel_offset);
|
||||
const int x1 = subpixel_snap(v0[0][0] - half_width - setup->pixel_offset);
|
||||
const int x2 = subpixel_snap(v0[0][0] + half_width - setup->pixel_offset);
|
||||
const int y0 = subpixel_snap(v0[0][1] - half_width - setup->pixel_offset);
|
||||
const int y1 = subpixel_snap(v0[0][1] + half_width - setup->pixel_offset);
|
||||
const int y2 = subpixel_snap(v0[0][1] + half_width - setup->pixel_offset);
|
||||
struct lp_scene *scene = lp_setup_get_current_scene(setup);
|
||||
struct lp_rast_triangle *point;
|
||||
unsigned bytes;
|
||||
struct u_rect bbox;
|
||||
unsigned nr_planes = 4;
|
||||
struct point_info info;
|
||||
|
||||
|
||||
/* Bounding rectangle (in pixels) */
|
||||
{
|
||||
/* Yes this is necessary to accurately calculate bounding boxes
|
||||
* with the two fill-conventions we support. GL (normally) ends
|
||||
* up needing a bottom-left fill convention, which requires
|
||||
* slightly different rounding.
|
||||
*/
|
||||
int adj = (setup->pixel_offset != 0) ? 1 : 0;
|
||||
|
||||
bbox.x0 = (MIN3(x0, x1, x2) + (FIXED_ONE-1)) >> FIXED_ORDER;
|
||||
bbox.x1 = (MAX3(x0, x1, x2) + (FIXED_ONE-1)) >> FIXED_ORDER;
|
||||
bbox.y0 = (MIN3(y0, y1, y2) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
|
||||
bbox.y1 = (MAX3(y0, y1, y2) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
|
||||
|
||||
/* Inclusive coordinates:
|
||||
*/
|
||||
bbox.x1--;
|
||||
bbox.y1--;
|
||||
}
|
||||
|
||||
if (!u_rect_test_intersection(&setup->draw_region, &bbox)) {
|
||||
if (0) debug_printf("offscreen\n");
|
||||
LP_COUNT(nr_culled_tris);
|
||||
return;
|
||||
}
|
||||
|
||||
u_rect_find_intersection(&setup->draw_region, &bbox);
|
||||
|
||||
point = lp_setup_alloc_triangle(scene,
|
||||
setup->fs.nr_inputs,
|
||||
nr_planes,
|
||||
&bytes);
|
||||
if (!point)
|
||||
return;
|
||||
|
||||
#ifdef DEBUG
|
||||
point->v[0][0] = v0[0][0];
|
||||
point->v[0][1] = v0[0][1];
|
||||
#endif
|
||||
|
||||
info.v0 = v0;
|
||||
info.dx01 = x1 - x0;
|
||||
info.dx12 = x2 - x1;
|
||||
info.dy01 = y1 - y0;
|
||||
info.dy12 = y2 - y1;
|
||||
|
||||
/* Setup parameter interpolants:
|
||||
*/
|
||||
setup_point_coefficients(setup, point, &info);
|
||||
|
||||
point->inputs.facing = 1.0F;
|
||||
point->inputs.state = setup->fs.stored;
|
||||
|
||||
{
|
||||
point->plane[0].dcdx = -1;
|
||||
point->plane[0].dcdy = 0;
|
||||
point->plane[0].c = 1-bbox.x0;
|
||||
point->plane[0].ei = 0;
|
||||
point->plane[0].eo = 1;
|
||||
|
||||
point->plane[1].dcdx = 1;
|
||||
point->plane[1].dcdy = 0;
|
||||
point->plane[1].c = bbox.x1+1;
|
||||
point->plane[1].ei = -1;
|
||||
point->plane[1].eo = 0;
|
||||
|
||||
point->plane[2].dcdx = 0;
|
||||
point->plane[2].dcdy = 1;
|
||||
point->plane[2].c = 1-bbox.y0;
|
||||
point->plane[2].ei = 0;
|
||||
point->plane[2].eo = 1;
|
||||
|
||||
point->plane[3].dcdx = 0;
|
||||
point->plane[3].dcdy = -1;
|
||||
point->plane[3].c = bbox.y1+1;
|
||||
point->plane[3].ei = -1;
|
||||
point->plane[3].eo = 0;
|
||||
}
|
||||
|
||||
lp_setup_bin_triangle(setup, point, &bbox, nr_planes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -125,6 +125,16 @@ compute_vertex_info(struct llvmpipe_context *llvmpipe)
|
||||
inputs[i].src_index = vinfo->num_attribs;
|
||||
draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index);
|
||||
}
|
||||
|
||||
/* Figure out if we need pointsize as well.
|
||||
*/
|
||||
llvmpipe->psize_slot = draw_find_shader_output(llvmpipe->draw,
|
||||
TGSI_SEMANTIC_PSIZE, 0);
|
||||
if (llvmpipe->psize_slot > 0) {
|
||||
draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT,
|
||||
llvmpipe->psize_slot);
|
||||
}
|
||||
|
||||
llvmpipe->num_inputs = lpfs->info.num_inputs;
|
||||
|
||||
draw_compute_vertex_size(vinfo);
|
||||
|
||||
@@ -75,6 +75,8 @@ llvmpipe_bind_rasterizer_state(struct pipe_context *pipe, void *handle)
|
||||
llvmpipe->rasterizer->flatshade_first);
|
||||
lp_setup_set_line_state( llvmpipe->setup,
|
||||
llvmpipe->rasterizer->line_width);
|
||||
lp_setup_set_point_state( llvmpipe->setup,
|
||||
llvmpipe->rasterizer->point_size);
|
||||
}
|
||||
|
||||
llvmpipe->dirty |= LP_NEW_RASTERIZER;
|
||||
|
||||
Reference in New Issue
Block a user