[Mesa-dev] [PATCH] llvmpipe: Honour pipe_rasterizer::point_quad_rasterization.
Marek Olšák
maraeo at gmail.com
Wed Jan 8 13:43:56 PST 2014
We have this "edge rule" state for points. It has 4 bits called Left,
Right, Top, Bottom. 1 means "in", 0 means "out". It probably
determines what happens if a primitive edge intersects a pixel or
something like that. We set Left=0, Right=1, Top=0, Bottom=1.
We also have this state:
ROUND_MODE
Controls conversion of X,Y coordinates from IEEE to fixed-point
POSSIBLE VALUES:
00 - 0 = Truncate (OGL)
01 - 1 = Round
02 - 2 = Round to Even (D3D)
03 - 3 = Round to Odd
Not sure what the correct values are for both states.
Marek
On Wed, Jan 8, 2014 at 8:56 PM, Roland Scheidegger <sroland at vmware.com> wrote:
> Am 08.01.2014 19:48, schrieb Marek Olšák:
>> On Wed, Jan 8, 2014 at 7:31 PM, Roland Scheidegger <sroland at vmware.com> wrote:
>>> Am 08.01.2014 19:12, schrieb Jose Fonseca:
>>>>
>>>>
>>>> ----- Original Message -----
>>>>> Am 08.01.2014 18:27, schrieb jfonseca at vmware.com:
>>>>>> From: José Fonseca <jfonseca at vmware.com>
>>>>>>
>>>>>> Commit eda21d2a3010d9fc5a68b55a843c5e44b2abf8dd fixed the rasterization
>>>>>> of points for Direct3D but ended up breaking the rasterization of OpenGL
>>>>>> non-sprite points, in particular conform's pntrast.c test.
>>>>>>
>>>>>> The only way to get both working is to properly honour
>>>>>> pipe_rasterizer::point_quad_rasterization, and follow the weird OpenGL
>>>>>> rule when it is false.
>>>>>> ---
>>>>>> src/gallium/drivers/llvmpipe/lp_setup_point.c | 64
>>>>>> ++++++++++++++++++++++-----
>>>>>> 1 file changed, 54 insertions(+), 10 deletions(-)
>>>>>>
>>>>>> diff --git a/src/gallium/drivers/llvmpipe/lp_setup_point.c
>>>>>> b/src/gallium/drivers/llvmpipe/lp_setup_point.c
>>>>>> index 988e0c5..e5ce4ee 100644
>>>>>> --- a/src/gallium/drivers/llvmpipe/lp_setup_point.c
>>>>>> +++ b/src/gallium/drivers/llvmpipe/lp_setup_point.c
>>>>>> @@ -338,9 +338,13 @@ try_setup_point( struct lp_setup_context *setup,
>>>>>> int fixed_width = MAX2(FIXED_ONE,
>>>>>> (subpixel_snap(size) + FIXED_ONE/2 - 1) &
>>>>>> ~(FIXED_ONE-1));
>>>>>>
>>>>>> - const int x0 = subpixel_snap(v0[0][0] - setup->pixel_offset) -
>>>>>> fixed_width/2;
>>>>>> - const int y0 = subpixel_snap(v0[0][1] - setup->pixel_offset) -
>>>>>> fixed_width/2;
>>>>>> -
>>>>>> + /* 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->bottom_edge_rule != 0) ? 1 : 0;
>>>>>> +
>>>>>> struct lp_scene *scene = setup->scene;
>>>>>> struct lp_rast_triangle *point;
>>>>>> unsigned bytes;
>>>>>> @@ -363,13 +367,14 @@ try_setup_point( struct lp_setup_context *setup,
>>>>>> print_point(setup, v0);
>>>>>>
>>>>>> /* 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.
>>>>>> + if (!lp_context->rasterizer ||
>>>>>> + lp_context->rasterizer->point_quad_rasterization) {
>>>>>> + /*
>>>>>> + * Rasterize points as quads.
>>>>>> */
>>>>>> - int adj = (setup->bottom_edge_rule != 0) ? 1 : 0;
>>>>>> +
>>>>>> + const int x0 = subpixel_snap(v0[0][0] - setup->pixel_offset) -
>>>>>> fixed_width/2;
>>>>>> + const int y0 = subpixel_snap(v0[0][1] - setup->pixel_offset) -
>>>>>> fixed_width/2;
>>>>>>
>>>>>> bbox.x0 = (x0 + (FIXED_ONE-1)) >> FIXED_ORDER;
>>>>>> bbox.x1 = (x0 + fixed_width + (FIXED_ONE-1)) >> FIXED_ORDER;
>>>>>> @@ -380,8 +385,47 @@ try_setup_point( struct lp_setup_context *setup,
>>>>>> */
>>>>>> bbox.x1--;
>>>>>> bbox.y1--;
>>>>>> + } else {
>>>>>> + /*
>>>>>> + * OpenGL rasterization rules for non-sprite points.
>>>>> Maybe add "legacy" here before OpenGL?
>>>>
>>>> Sure.
>>>>
>>>>>> + *
>>>>>> + * Per OpenGL 2.1 spec, section 3.3.1, "Basic Point Rasterization".
>>>>>> + */
>>>>>> +
>>>>>> + const int x0 = subpixel_snap(v0[0][0]);
>>>>>> + const int y0 = subpixel_snap(v0[0][1]) - adj;
>>>>>> +
>>>>>> + int int_width = fixed_width >> FIXED_ORDER;
>>>>>> +
>>>>>> + assert(setup->pixel_offset != 0);
>>>>>> +
>>>>>> + if (int_width == 1) {
>>>>>> + bbox.x0 = x0 >> FIXED_ORDER;
>>>>>> + bbox.y0 = y0 >> FIXED_ORDER;
>>>>>> + bbox.x1 = bbox.x0;
>>>>>> + bbox.y1 = bbox.y0;
>>>>>> + } else {
>>>>>> + if (int_width & 1) {
>>>>>> + /* Odd width */
>>>>>> + bbox.x0 = (x0 >> FIXED_ORDER) - (int_width - 1)/2;
>>>>>> + bbox.y0 = (y0 >> FIXED_ORDER) - (int_width - 1)/2;
>>>>>> + } else {
>>>>>> + /* Even width */
>>>>>> + bbox.x0 = ((x0 + FIXED_ONE/2) >> FIXED_ORDER) - int_width/2;
>>>>>> + bbox.y0 = ((y0 + FIXED_ONE/2) >> FIXED_ORDER) - int_width/2;
>>>>>> + }
>>>>>> +
>>>>>> + bbox.x1 = bbox.x0 + int_width - 1;
>>>>>> + bbox.y1 = bbox.y0 + int_width - 1;
>>>>>> + }
>>>>>> }
>>>>>> -
>>>>>> +
>>>>>> + if (0) {
>>>>>> + debug_printf(" bbox: (%i, %i) - (%i, %i)\n",
>>>>>> + bbox.x0, bbox.y0,
>>>>>> + bbox.x1, bbox.y1);
>>>>>> + }
>>>>>> +
>>>>>> if (!u_rect_test_intersection(&setup->draw_regions[viewport_index],
>>>>>> &bbox)) {
>>>>>> if (0) debug_printf("offscreen\n");
>>>>>> LP_COUNT(nr_culled_tris);
>>>>>>
>>>>>
>>>>> This looks good to me. Note though this type of point rasterization is
>>>>> only available in pre 3.0 contexts (or compatibilility contexts which we
>>>>> don't support) anyway.
>>>>
>>>> Oh really!? Argh.. It though it was still relevant nowadays, or I wouldn't have wasted my afternoon on trying to figure out the regression and the proper fix...
>>> Well it seems at least some hw (nvidia for one) still can follow these
>>> rules, so maybe there are apps out there which rely on it (radeonsi otoh
>>> ignores the state). At least conform relies on it apparently so it's not
>>> really a waste :-).
>>
>> I have never understood what point_quad_rasterization means and how we
>> should use it. I think Radeons always rasterize points as axis-aligned
>> rectangles (width and height can be different) and there is no support
>> for round/smooth points as far as I know.
>
> Noone can do round/smooth points afaik and they always need to be
> emulated. The problem is that even square points had different
> rasterization rules to point sprites, that is they render differently to
> what 2 tris (or a tri-strip) with the corners placed where'd they show
> up depending on the point center and the point size would - in
> particular the stuff about rounding widht to whole integers then doing
> things differently depending if the width is odd or even is the crazy
> part. The difference may be somewhat subtle in practice I guess but
> presumably you can't pass the conform test if you just render them
> according to "new" (point sprite) rules.
> I have no idea though if you could set some bits in your hw so it would
> match legacy GL point rasterization rules.
>
> Roland
More information about the mesa-dev
mailing list