1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* libs/pixelflinger/trap.cpp
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Copyright 2006, The Android Open Source Project
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** you may not use this file except in compliance with the License.
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** You may obtain a copy of the License at
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** See the License for the specific language governing permissions and
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** limitations under the License.
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <assert.h>
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "trap.h"
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "picker.h"
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/log.h>
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/memory.h>
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectnamespace android {
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// enable to see triangles edges
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DEBUG_TRANGLES  0
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void pointx_validate(void *con, const GGLcoord* c, GGLcoord r);
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void pointx(void *con, const GGLcoord* c, GGLcoord r);
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void aa_pointx(void *con, const GGLcoord* c, GGLcoord r);
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void aa_nice_pointx(void *con, const GGLcoord* c, GGLcoord r);
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void linex_validate(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord w);
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void linex(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord w);
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void aa_linex(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord w);
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void recti_validate(void* c, GGLint l, GGLint t, GGLint r, GGLint b);
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void recti(void* c, GGLint l, GGLint t, GGLint r, GGLint b);
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void trianglex_validate(void*,
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLcoord*, const GGLcoord*, const GGLcoord*);
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void trianglex_small(void*,
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLcoord*, const GGLcoord*, const GGLcoord*);
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void trianglex_big(void*,
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLcoord*, const GGLcoord*, const GGLcoord*);
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void aa_trianglex(void*,
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLcoord*, const GGLcoord*, const GGLcoord*);
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void trianglex_debug(void* con,
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLcoord*, const GGLcoord*, const GGLcoord*);
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void aapolyx(void* con,
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLcoord* pts, int count);
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline int min(int a, int b) CONST;
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline int max(int a, int b) CONST;
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline int min(int a, int b, int c) CONST;
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline int max(int a, int b, int c) CONST;
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if 0
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#pragma mark -
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#pragma mark Tools
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline int min(int a, int b) {
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return a<b ? a : b;
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline int max(int a, int b) {
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return a<b ? b : a;
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline int min(int a, int b, int c) {
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return min(a,min(b,c));
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectinline int max(int a, int b, int c) {
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return max(a,max(b,c));
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttemplate <typename T>
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline void swap(T& a, T& b) {
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    T t(a);
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    a = b;
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    b = t;
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttriangle_dump_points( const GGLcoord*  v0,
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                      const GGLcoord*  v1,
978d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block                      const GGLcoord*  v2 )
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    float tri = 1.0f / TRI_ONE;
1008d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block    ALOGD("  P0=(%.3f, %.3f)  [%08x, %08x]\n"
1018d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block          "  P1=(%.3f, %.3f)  [%08x, %08x]\n"
1028d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block          "  P2=(%.3f, %.3f)  [%08x, %08x]\n",
1038d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block          v0[0]*tri, v0[1]*tri, v0[0], v0[1],
1048d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block          v1[0]*tri, v1[1]*tri, v1[0], v1[1],
1058d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block          v2[0]*tri, v2[1]*tri, v2[0], v2[1] );
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if 0
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#pragma mark -
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#pragma mark Misc
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid ggl_init_trap(context_t* c)
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE|GGL_TMU_STATE|GGL_CB_STATE);
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid ggl_state_changed(context_t* c, int flags)
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ggl_likely(!c->dirty)) {
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->procs.pointx     = pointx_validate;
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->procs.linex      = linex_validate;
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->procs.recti      = recti_validate;
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->procs.trianglex  = trianglex_validate;
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    c->dirty |= uint32_t(flags);
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if 0
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#pragma mark -
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#pragma mark Point
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid pointx_validate(void *con, const GGLcoord* v, GGLcoord rad)
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGL_CONTEXT(c, con);
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ggl_pick(c);
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (c->state.needs.p & GGL_NEED_MASK(P_AA)) {
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (c->state.enables & GGL_ENABLE_POINT_AA_NICE) {
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c->procs.pointx = aa_nice_pointx;
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c->procs.pointx = aa_pointx;
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->procs.pointx = pointx;
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    c->procs.pointx(con, v, rad);
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid pointx(void *con, const GGLcoord* v, GGLcoord rad)
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGL_CONTEXT(c, con);
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLcoord halfSize = TRI_ROUND(rad) >> 1;
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (halfSize == 0)
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        halfSize = TRI_HALF;
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLcoord xc = v[0];
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLcoord yc = v[1];
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (halfSize & TRI_HALF) { // size odd
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        xc = TRI_FLOOR(xc) + TRI_HALF;
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        yc = TRI_FLOOR(yc) + TRI_HALF;
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else { // size even
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        xc = TRI_ROUND(xc);
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        yc = TRI_ROUND(yc);
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLint l = (xc - halfSize) >> TRI_FRACTION_BITS;
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLint t = (yc - halfSize) >> TRI_FRACTION_BITS;
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLint r = (xc + halfSize) >> TRI_FRACTION_BITS;
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLint b = (yc + halfSize) >> TRI_FRACTION_BITS;
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    recti(c, l, t, r, b);
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// This way of computing the coverage factor, is more accurate and gives
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// better results for small circles, but it is also a lot slower.
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// Here we use super-sampling.
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int32_t coverageNice(GGLcoord x, GGLcoord y,
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        GGLcoord rmin, GGLcoord rmax, GGLcoord rr)
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const GGLcoord d2 = x*x + y*y;
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (d2 >= rmax) return 0;
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (d2 < rmin)  return 0x7FFF;
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int kSamples              =  4;
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int kInc                  =  4;    // 1/4 = 0.25
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int kCoverageUnit         =  1;    // 1/(4^2) = 0.0625
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const GGLcoord kCoordOffset     = -6;    // -0.375
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int hits = 0;
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int x_sample = x + kCoordOffset;
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (int i=0 ; i<kSamples ; i++, x_sample += kInc) {
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const int xval = rr - (x_sample * x_sample);
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int y_sample = y + kCoordOffset;
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        for (int j=0 ; j<kSamples ; j++, y_sample += kInc) {
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (xval - (y_sample * y_sample) > 0)
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                hits += kCoverageUnit;
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return min(0x7FFF, hits << (15 - kSamples));
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid aa_nice_pointx(void *con, const GGLcoord* v, GGLcoord size)
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGL_CONTEXT(c, con);
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLcoord rad = ((size + 1)>>1);
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLint l = (v[0] - rad) >> TRI_FRACTION_BITS;
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLint t = (v[1] - rad) >> TRI_FRACTION_BITS;
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLint r = (v[0] + rad + (TRI_ONE-1)) >> TRI_FRACTION_BITS;
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLint b = (v[1] + rad + (TRI_ONE-1)) >> TRI_FRACTION_BITS;
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLcoord xstart = TRI_FROM_INT(l) - v[0] + TRI_HALF;
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLcoord ystart = TRI_FROM_INT(t) - v[1] + TRI_HALF;
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // scissor...
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (l < GGLint(c->state.scissor.left)) {
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        xstart += TRI_FROM_INT(c->state.scissor.left-l);
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        l = GGLint(c->state.scissor.left);
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (t < GGLint(c->state.scissor.top)) {
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ystart += TRI_FROM_INT(c->state.scissor.top-t);
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        t = GGLint(c->state.scissor.top);
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (r > GGLint(c->state.scissor.right)) {
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        r = GGLint(c->state.scissor.right);
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (b > GGLint(c->state.scissor.bottom)) {
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        b = GGLint(c->state.scissor.bottom);
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int xc = r - l;
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int yc = b - t;
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (xc>0 && yc>0) {
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int16_t* covPtr = c->state.buffers.coverage;
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const int32_t sqr2Over2 = 0xC; // rounded up
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        GGLcoord rr = rad*rad;
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        GGLcoord rmin = (rad - sqr2Over2)*(rad - sqr2Over2);
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        GGLcoord rmax = (rad + sqr2Over2)*(rad + sqr2Over2);
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        GGLcoord y = ystart;
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->iterators.xl = l;
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->iterators.xr = r;
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->init_y(c, t);
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        do {
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // compute coverage factors for each pixel
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            GGLcoord x = xstart;
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (int i=l ; i<r ; i++) {
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                covPtr[i] = coverageNice(x, y, rmin, rmax, rr);
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                x += TRI_ONE;
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            y += TRI_ONE;
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c->scanline(c);
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c->step_y(c);
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } while (--yc);
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// This is a cheap way of computing the coverage factor for a circle.
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// We just lerp between the circles of radii r-sqrt(2)/2 and r+sqrt(2)/2
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline int32_t coverageFast(GGLcoord x, GGLcoord y,
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        GGLcoord rmin, GGLcoord rmax, GGLcoord scale)
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const GGLcoord d2 = x*x + y*y;
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (d2 >= rmax) return 0;
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (d2 < rmin)  return 0x7FFF;
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0x7FFF - (d2-rmin)*scale;
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid aa_pointx(void *con, const GGLcoord* v, GGLcoord size)
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGL_CONTEXT(c, con);
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLcoord rad = ((size + 1)>>1);
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLint l = (v[0] - rad) >> TRI_FRACTION_BITS;
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLint t = (v[1] - rad) >> TRI_FRACTION_BITS;
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLint r = (v[0] + rad + (TRI_ONE-1)) >> TRI_FRACTION_BITS;
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLint b = (v[1] + rad + (TRI_ONE-1)) >> TRI_FRACTION_BITS;
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLcoord xstart = TRI_FROM_INT(l) - v[0] + TRI_HALF;
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLcoord ystart = TRI_FROM_INT(t) - v[1] + TRI_HALF;
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // scissor...
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (l < GGLint(c->state.scissor.left)) {
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        xstart += TRI_FROM_INT(c->state.scissor.left-l);
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        l = GGLint(c->state.scissor.left);
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (t < GGLint(c->state.scissor.top)) {
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ystart += TRI_FROM_INT(c->state.scissor.top-t);
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        t = GGLint(c->state.scissor.top);
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (r > GGLint(c->state.scissor.right)) {
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        r = GGLint(c->state.scissor.right);
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (b > GGLint(c->state.scissor.bottom)) {
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        b = GGLint(c->state.scissor.bottom);
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int xc = r - l;
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int yc = b - t;
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (xc>0 && yc>0) {
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int16_t* covPtr = c->state.buffers.coverage;
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        rad <<= 4;
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const int32_t sqr2Over2 = 0xB5;    // fixed-point 24.8
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        GGLcoord rmin = rad - sqr2Over2;
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        GGLcoord rmax = rad + sqr2Over2;
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        GGLcoord scale;
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        rmin *= rmin;
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        rmax *= rmax;
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        scale = 0x800000 / (rmax - rmin);
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        rmin >>= 8;
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        rmax >>= 8;
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        GGLcoord y = ystart;
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->iterators.xl = l;
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->iterators.xr = r;
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->init_y(c, t);
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        do {
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // compute coverage factors for each pixel
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            GGLcoord x = xstart;
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (int i=l ; i<r ; i++) {
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                covPtr[i] = coverageFast(x, y, rmin, rmax, scale);
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                x += TRI_ONE;
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            y += TRI_ONE;
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c->scanline(c);
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c->step_y(c);
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } while (--yc);
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if 0
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#pragma mark -
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#pragma mark Line
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid linex_validate(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord w)
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGL_CONTEXT(c, con);
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ggl_pick(c);
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (c->state.needs.p & GGL_NEED_MASK(P_AA)) {
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->procs.linex = aa_linex;
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->procs.linex = linex;
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    c->procs.linex(con, v0, v1, w);
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void linex(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord width)
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGL_CONTEXT(c, con);
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLcoord v[4][2];
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v[0][0] = v0[0];    v[0][1] = v0[1];
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v[1][0] = v1[0];    v[1][1] = v1[1];
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v0 = v[0];
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v1 = v[1];
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const GGLcoord dx = abs(v0[0] - v1[0]);
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const GGLcoord dy = abs(v0[1] - v1[1]);
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLcoord nx, ny;
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    nx = ny = 0;
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLcoord halfWidth = TRI_ROUND(width) >> 1;
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (halfWidth == 0)
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        halfWidth = TRI_HALF;
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ((dx > dy) ? ny : nx) = halfWidth;
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v[2][0] = v1[0];    v[2][1] = v1[1];
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v[3][0] = v0[0];    v[3][1] = v0[1];
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v[0][0] += nx;      v[0][1] += ny;
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v[1][0] += nx;      v[1][1] += ny;
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v[2][0] -= nx;      v[2][1] -= ny;
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v[3][0] -= nx;      v[3][1] -= ny;
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    trianglex_big(con, v[0], v[1], v[2]);
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    trianglex_big(con, v[0], v[2], v[3]);
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void aa_linex(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord width)
377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGL_CONTEXT(c, con);
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLcoord v[4][2];
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v[0][0] = v0[0];    v[0][1] = v0[1];
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v[1][0] = v1[0];    v[1][1] = v1[1];
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v0 = v[0];
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v1 = v[1];
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const GGLcoord dx = v0[0] - v1[0];
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const GGLcoord dy = v0[1] - v1[1];
387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLcoord nx = -dy;
388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLcoord ny =  dx;
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // generally, this will be well below 1.0
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const GGLfixed norm = gglMulx(width, gglSqrtRecipx(nx*nx+ny*ny), 4);
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    nx = gglMulx(nx, norm, 21);
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ny = gglMulx(ny, norm, 21);
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v[2][0] = v1[0];    v[2][1] = v1[1];
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v[3][0] = v0[0];    v[3][1] = v0[1];
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v[0][0] += nx;      v[0][1] += ny;
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v[1][0] += nx;      v[1][1] += ny;
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v[2][0] -= nx;      v[2][1] -= ny;
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    v[3][0] -= nx;      v[3][1] -= ny;
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    aapolyx(con, v[0], 4);
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if 0
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#pragma mark -
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#pragma mark Rect
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid recti_validate(void *con, GGLint l, GGLint t, GGLint r, GGLint b)
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGL_CONTEXT(c, con);
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ggl_pick(c);
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    c->procs.recti = recti;
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    c->procs.recti(con, l, t, r, b);
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid recti(void* con, GGLint l, GGLint t, GGLint r, GGLint b)
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGL_CONTEXT(c, con);
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // scissor...
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (l < GGLint(c->state.scissor.left))
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        l = GGLint(c->state.scissor.left);
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (t < GGLint(c->state.scissor.top))
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        t = GGLint(c->state.scissor.top);
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (r > GGLint(c->state.scissor.right))
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        r = GGLint(c->state.scissor.right);
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (b > GGLint(c->state.scissor.bottom))
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        b = GGLint(c->state.scissor.bottom);
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int xc = r - l;
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int yc = b - t;
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (xc>0 && yc>0) {
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->iterators.xl = l;
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->iterators.xr = r;
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->init_y(c, t);
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->rect(c, yc);
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if 0
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#pragma mark -
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#pragma mark Triangle / Debugging
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void scanline_set(context_t* c)
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t x = c->iterators.xl;
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    size_t ct = c->iterators.xr - x;
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t y = c->iterators.y;
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    surface_t* cb = &(c->state.buffers.color);
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const GGLFormat* fp = &(c->formats[cb->format]);
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint8_t* dst = reinterpret_cast<uint8_t*>(cb->data) +
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                            (x + (cb->stride * y)) * fp->size;
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const size_t size = ct * fp->size;
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(dst, 0xFF, size);
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void trianglex_debug(void* con,
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLcoord* v0, const GGLcoord* v1, const GGLcoord* v2)
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGL_CONTEXT(c, con);
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (c->state.needs.p & GGL_NEED_MASK(P_AA)) {
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        aa_trianglex(con,v0,v1,v2);
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        trianglex_big(con,v0,v1,v2);
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	void (*save_scanline)(context_t*)  = c->scanline;
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    c->scanline = scanline_set;
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    linex(con, v0, v1, TRI_ONE);
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    linex(con, v1, v2, TRI_ONE);
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    linex(con, v2, v0, TRI_ONE);
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    c->scanline = save_scanline;
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void trianglex_xor(void* con,
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLcoord* v0, const GGLcoord* v1, const GGLcoord* v2)
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    trianglex_big(con,v0,v1,v2);
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    trianglex_small(con,v0,v1,v2);
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if 0
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#pragma mark -
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#pragma mark Triangle
490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid trianglex_validate(void *con,
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLcoord* v0, const GGLcoord* v1, const GGLcoord* v2)
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGL_CONTEXT(c, con);
496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ggl_pick(c);
497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (c->state.needs.p & GGL_NEED_MASK(P_AA)) {
498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->procs.trianglex = DEBUG_TRANGLES ? trianglex_debug : aa_trianglex;
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->procs.trianglex = DEBUG_TRANGLES ? trianglex_debug : trianglex_big;
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    c->procs.trianglex(con, v0, v1, v2);
503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid trianglex_small(void* con,
508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLcoord* v0, const GGLcoord* v1, const GGLcoord* v2)
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGL_CONTEXT(c, con);
511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // vertices are in 28.4 fixed point, which allows
513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // us to use 32 bits multiplies below.
514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t x0 = v0[0];
515dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t y0 = v0[1];
516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t x1 = v1[0];
517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t y1 = v1[1];
518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t x2 = v2[0];
519dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t y2 = v2[1];
520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t dx01 = x0 - x1;
522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t dy20 = y2 - y0;
523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t dy01 = y0 - y1;
524dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t dx20 = x2 - x0;
525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // The code below works only with CCW triangles
527dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // so if we get a CW triangle, we need to swap two of its vertices
528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (dx01*dy20 < dy01*dx20) {
529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        swap(x0, x1);
530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        swap(y0, y1);
531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dx01 = x0 - x1;
532dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dy01 = y0 - y1;
533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dx20 = x2 - x0;
534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dy20 = y2 - y0;
535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
536dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t dx12 = x1 - x2;
537dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t dy12 = y1 - y2;
538dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
539dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // bounding box & scissor
540dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int32_t bminx = TRI_FLOOR(min(x0, x1, x2)) >> TRI_FRACTION_BITS;
541dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int32_t bminy = TRI_FLOOR(min(y0, y1, y2)) >> TRI_FRACTION_BITS;
542dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int32_t bmaxx = TRI_CEIL( max(x0, x1, x2)) >> TRI_FRACTION_BITS;
543dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int32_t bmaxy = TRI_CEIL( max(y0, y1, y2)) >> TRI_FRACTION_BITS;
544dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int32_t minx = max(bminx, c->state.scissor.left);
545dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int32_t miny = max(bminy, c->state.scissor.top);
546dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int32_t maxx = min(bmaxx, c->state.scissor.right);
547dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int32_t maxy = min(bmaxy, c->state.scissor.bottom);
548dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if ((minx >= maxx) || (miny >= maxy))
549dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return; // too small or clipped out...
550dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
551dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // step equations to the bounding box and snap to pixel center
552dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int32_t my = (miny << TRI_FRACTION_BITS) + TRI_HALF;
553dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int32_t mx = (minx << TRI_FRACTION_BITS) + TRI_HALF;
554dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t ey0 = dy01 * (x0 - mx) - dx01 * (y0 - my);
555dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t ey1 = dy12 * (x1 - mx) - dx12 * (y1 - my);
556dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t ey2 = dy20 * (x2 - mx) - dx20 * (y2 - my);
557dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
558dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // right-exclusive fill rule, to avoid rare cases
559dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // of over drawing
560dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (dy01<0 || (dy01 == 0 && dx01>0)) ey0++;
561dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (dy12<0 || (dy12 == 0 && dx12>0)) ey1++;
562dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (dy20<0 || (dy20 == 0 && dx20>0)) ey2++;
563dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
564dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    c->init_y(c, miny);
565dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (int32_t y = miny; y < maxy; y++) {
566dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        register int32_t ex0 = ey0;
567dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        register int32_t ex1 = ey1;
568dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        register int32_t ex2 = ey2;
569dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        register int32_t xl, xr;
570dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        for (xl=minx ; xl<maxx ; xl++) {
571dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (ex0>0 && ex1>0 && ex2>0)
572dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break; // all strictly positive
573dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ex0 -= dy01 << TRI_FRACTION_BITS;
574dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ex1 -= dy12 << TRI_FRACTION_BITS;
575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ex2 -= dy20 << TRI_FRACTION_BITS;
576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        xr = xl;
578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        for ( ; xr<maxx ; xr++) {
579dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (!(ex0>0 && ex1>0 && ex2>0))
580dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break; // not all strictly positive
581dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ex0 -= dy01 << TRI_FRACTION_BITS;
582dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ex1 -= dy12 << TRI_FRACTION_BITS;
583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ex2 -= dy20 << TRI_FRACTION_BITS;
584dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
585dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
586dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (xl < xr) {
587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c->iterators.xl = xl;
588dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c->iterators.xr = xr;
589dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c->scanline(c);
590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->step_y(c);
592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
593dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ey0 += dx01 << TRI_FRACTION_BITS;
594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ey1 += dx12 << TRI_FRACTION_BITS;
595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ey2 += dx20 << TRI_FRACTION_BITS;
596dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
597dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
598dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if 0
601dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#pragma mark -
602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
603dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// the following routine fills a triangle via edge stepping, which
605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// unfortunately requires divisions in the setup phase to get right,
606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// it should probably only be used for relatively large trianges
607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// x = y*DX/DY    (ou DX and DY are constants, DY > 0, et y >= 0)
610dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//
611dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// for an equation of the type:
612dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//      x' = y*K/2^p     (with K and p constants "carefully chosen")
613dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//
614dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// We can now do a DDA without precision loss. We define 'e' by:
615dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//      x' - x = y*(DX/DY - K/2^p) = y*e
616dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//
617dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// If we choose K = round(DX*2^p/DY) then,
618dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//      abs(e) <= 1/2^(p+1) by construction
619dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//
620dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// therefore abs(x'-x) = y*abs(e) <= y/2^(p+1) <= DY/2^(p+1) <= DMAX/2^(p+1)
621dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//
622dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// which means that if DMAX <= 2^p, therefore abs(x-x') <= 1/2, including
623dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// at the last line. In fact, it's even a strict inequality except in one
624dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// extrem case (DY == DMAX et e = +/- 1/2)
625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//
626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// Applying that to our coordinates, we need 2^p >= 4096*16 = 65536
627dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// so p = 16 is enough, we're so lucky!
628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
629dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectconst int TRI_ITERATORS_BITS = 16;
630dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
631dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct Edge
632dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
633dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  int32_t  x;      // edge position in 16.16 coordinates
634dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  int32_t  x_incr; // on each step, increment x by that amount
635dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  int32_t  y_top;  // starting scanline, 16.4 format
636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  int32_t  y_bot;
637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectedge_dump( Edge*  edge )
641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
642fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block  ALOGI( "  top=%d (%.3f)  bot=%d (%.3f)  x=%d (%.3f)  ix=%d (%.3f)",
643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        edge->y_top, edge->y_top/float(TRI_ONE),
644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		edge->y_bot, edge->y_bot/float(TRI_ONE),
645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		edge->x, edge->x/float(FIXED_ONE),
646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		edge->x_incr, edge->x_incr/float(FIXED_ONE) );
647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttriangle_dump_edges( Edge*  edges,
651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                     int            count )
652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
653fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block    ALOGI( "%d edge%s:\n", count, count == 1 ? "" : "s" );
654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	for ( ; count > 0; count--, edges++ )
655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  edge_dump( edges );
656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// the following function sets up an edge, it assumes
659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// that ymin and ymax are in already in the 'reduced'
660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// format
661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic __attribute__((noinline))
662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid edge_setup(
663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        Edge*           edges,
664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int*            pcount,
665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLcoord* p1,
666dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLcoord* p2,
667dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int32_t         ymin,
668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int32_t         ymax )
669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
670dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	const GGLfixed*  top = p1;
671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	const GGLfixed*  bot = p2;
672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	Edge*    edge = edges + *pcount;
673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (top[1] > bot[1]) {
675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        swap(top, bot);
676dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
678dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int  y1 = top[1] | 1;
679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int  y2 = bot[1] | 1;
680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int  dy = y2 - y1;
681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if ( dy == 0 || y1 > ymax || y2 < ymin )
683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return;
684dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if ( y1 > ymin )
686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ymin = TRI_SNAP_NEXT_HALF(y1);
687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if ( y2 < ymax )
689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ymax = TRI_SNAP_PREV_HALF(y2);
690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if ( ymin > ymax )  // when the edge doesn't cross any scanline
692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	  return;
693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	const int x1 = top[0];
695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	const int dx = bot[0] - x1;
696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int shift = TRI_ITERATORS_BITS - TRI_FRACTION_BITS;
697dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	// setup edge fields
699dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // We add 0.5 to edge->x here because it simplifies the rounding
700dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // in triangle_sweep_edges() -- this doesn't change the ordering of 'x'
701dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	edge->x      = (x1 << shift) + (1LU << (TRI_ITERATORS_BITS-1));
702dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	edge->x_incr = 0;
703dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	edge->y_top  = ymin;
704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	edge->y_bot  = ymax;
705dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
706dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (ggl_likely(ymin <= ymax && dx)) {
707dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        edge->x_incr = gglDivQ16(dx, dy);
708dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ggl_likely(y1 < ymin)) {
710dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int32_t xadjust = (edge->x_incr * (ymin-y1)) >> TRI_FRACTION_BITS;
711dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        edge->x += xadjust;
712dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
713dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
714dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	++*pcount;
715dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
716dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
717dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
718dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
719dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttriangle_sweep_edges( Edge*  left,
720dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                      Edge*  right,
721dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					  int            ytop,
722dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					  int            ybot,
723dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					  context_t*     c )
724dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
725dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int count = ((ybot - ytop)>>TRI_FRACTION_BITS) + 1;
726dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (count<=0) return;
727dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
728dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // sort the edges horizontally
729dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if ((left->x > right->x) ||
730dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ((left->x == right->x) && (left->x_incr > right->x_incr))) {
731dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        swap(left, right);
732dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
733dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
734dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int left_x = left->x;
735dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int right_x = right->x;
736dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int left_xi = left->x_incr;
737dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int right_xi  = right->x_incr;
738dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    left->x  += left_xi * count;
739dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    right->x += right_xi * count;
740dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
741dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	const int xmin = c->state.scissor.left;
742dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	const int xmax = c->state.scissor.right;
743dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do {
744dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // horizontal scissoring
745dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const int32_t xl = max(left_x  >> TRI_ITERATORS_BITS, xmin);
746dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const int32_t xr = min(right_x >> TRI_ITERATORS_BITS, xmax);
747dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        left_x  += left_xi;
748dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        right_x += right_xi;
749dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // invoke the scanline rasterizer
750dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (ggl_likely(xl < xr)) {
751dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c->iterators.xl = xl;
752dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c->iterators.xr = xr;
753dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c->scanline(c);
754dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
755dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		c->step_y(c);
756dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	} while (--count);
757dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
758dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
759dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
760dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid trianglex_big(void* con,
761dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLcoord* v0, const GGLcoord* v1, const GGLcoord* v2)
762dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
763dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGL_CONTEXT(c, con);
764dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
765dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Edge edges[3];
766dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int num_edges = 0;
767dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int32_t ymin = TRI_FROM_INT(c->state.scissor.top)    + TRI_HALF;
768dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int32_t ymax = TRI_FROM_INT(c->state.scissor.bottom) - TRI_HALF;
769dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
770dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	edge_setup( edges, &num_edges, v0, v1, ymin, ymax );
771dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	edge_setup( edges, &num_edges, v0, v2, ymin, ymax );
772dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	edge_setup( edges, &num_edges, v1, v2, ymin, ymax );
773dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
774dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ggl_unlikely(num_edges<2))  // for really tiny triangles that don't
775dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return;                     // cross any scanline centers
776dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
777dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Edge* left  = &edges[0];
778dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Edge* right = &edges[1];
779dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Edge* other = &edges[2];
780dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t y_top = min(left->y_top, right->y_top);
781dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t y_bot = max(left->y_bot, right->y_bot);
782dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
783dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (ggl_likely(num_edges==3)) {
784dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        y_top = min(y_top, edges[2].y_top);
785dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        y_bot = max(y_bot, edges[2].y_bot);
786dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (edges[0].y_top > y_top) {
787dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            other = &edges[0];
788dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            left  = &edges[2];
789dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		} else if (edges[1].y_top > y_top) {
790dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            other = &edges[1];
791dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            right = &edges[2];
792dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
793dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
794dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
795dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    c->init_y(c, y_top >> TRI_FRACTION_BITS);
796dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
797dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t y_mid = min(left->y_bot, right->y_bot);
798dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    triangle_sweep_edges( left, right, y_top, y_mid, c );
799dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
800dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // second scanline sweep loop, if necessary
801dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    y_mid += TRI_ONE;
802dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (y_mid <= y_bot) {
803dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ((left->y_bot == y_bot) ? right : left) = other;
804dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (other->y_top < y_mid) {
805dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            other->x += other->x_incr;
806dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
807dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        triangle_sweep_edges( left, right, y_mid, y_bot, c );
808dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
809dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
810dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
811dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid aa_trianglex(void* con,
812dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLcoord* a, const GGLcoord* b, const GGLcoord* c)
813dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
814dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLcoord pts[6] = { a[0], a[1], b[0], b[1], c[0], c[1] };
815dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    aapolyx(con, pts, 3);
816dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
817dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
818dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// ----------------------------------------------------------------------------
819dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if 0
820dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#pragma mark -
821dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
822dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
823dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct AAEdge
824dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
825dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLfixed x;         // edge position in 12.16 coordinates
826dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLfixed x_incr;    // on each y step, increment x by that amount
827dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLfixed y_incr;    // on each x step, increment y by that amount
828dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int16_t y_top;      // starting scanline, 12.4 format
829dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int16_t y_bot;      // starting scanline, 12.4 format
830dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void dump();
831dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
832dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
833dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid AAEdge::dump()
834dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
835dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    float tri  = 1.0f / TRI_ONE;
836dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    float iter = 1.0f / (1<<TRI_ITERATORS_BITS);
837dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    float fix  = 1.0f / FIXED_ONE;
8388d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block    ALOGD(   "x=%08x (%.3f), "
839dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "x_incr=%08x (%.3f), y_incr=%08x (%.3f), "
840dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            "y_top=%08x (%.3f), y_bot=%08x (%.3f) ",
841dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        x, x*fix,
842dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        x_incr, x_incr*iter,
843dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        y_incr, y_incr*iter,
844dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        y_top, y_top*tri,
845dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        y_bot, y_bot*tri );
846dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
847dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
848dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// the following function sets up an edge, it assumes
849dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// that ymin and ymax are in already in the 'reduced'
850dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// format
851dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic __attribute__((noinline))
852dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid aa_edge_setup(
853dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        AAEdge*         edges,
854dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int*            pcount,
855dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLcoord* p1,
856dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLcoord* p2,
857dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int32_t         ymin,
858dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int32_t         ymax )
859dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
860dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const GGLfixed*  top = p1;
861dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const GGLfixed*  bot = p2;
862dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AAEdge* edge = edges + *pcount;
863dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
864dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (top[1] > bot[1])
865dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        swap(top, bot);
866dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
867dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int  y1 = top[1];
868dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int  y2 = bot[1];
869dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int  dy = y2 - y1;
870dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
871dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (dy==0 || y1>ymax || y2<ymin)
872dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
873dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
874dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (y1 > ymin)
875dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ymin = y1;
876dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
877dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (y2 < ymax)
878dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ymax = y2;
879dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
880dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int x1 = top[0];
881dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int dx = bot[0] - x1;
882dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int shift = FIXED_BITS - TRI_FRACTION_BITS;
883dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
884dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // setup edge fields
885dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    edge->x      = x1 << shift;
886dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    edge->x_incr = 0;
887dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    edge->y_top  = ymin;
888dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    edge->y_bot  = ymax;
889dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    edge->y_incr = 0x7FFFFFFF;
890dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
891dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ggl_likely(ymin <= ymax && dx)) {
892dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        edge->x_incr = gglDivQ16(dx, dy);
893dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (dx != 0) {
894dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            edge->y_incr = abs(gglDivQ16(dy, dx));
895dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
896dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
897dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ggl_likely(y1 < ymin)) {
898dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int32_t xadjust = (edge->x_incr * (ymin-y1))
899dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                >> (TRI_FRACTION_BITS + TRI_ITERATORS_BITS - FIXED_BITS);
900dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        edge->x += xadjust;
901dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
902dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
903dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ++*pcount;
904dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
905dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
906dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
907dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef int (*compar_t)(const void*, const void*);
908dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int compare_edges(const AAEdge *e0, const AAEdge *e1) {
909dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (e0->y_top > e1->y_top)      return 1;
910dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (e0->y_top < e1->y_top)      return -1;
911dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (e0->x > e1->x)              return 1;
912dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (e0->x < e1->x)              return -1;
913dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (e0->x_incr > e1->x_incr)    return 1;
914dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (e0->x_incr < e1->x_incr)    return -1;
915dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0; // same edges, should never happen
916dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
917dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
918dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline
919dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid SET_COVERAGE(int16_t*& p, int32_t value, ssize_t n)
920dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
921dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    android_memset16((uint16_t*)p, value, n*2);
922dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p += n;
923dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
924dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
925dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline
926dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid ADD_COVERAGE(int16_t*& p, int32_t value)
927dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
928dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    value = *p + value;
929dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (value >= 0x8000)
930dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        value = 0x7FFF;
931dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    *p++ = value;
932dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
933dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
934dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline
935dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid SUB_COVERAGE(int16_t*& p, int32_t value)
936dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
937dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    value = *p - value;
938dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    value &= ~(value>>31);
939dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    *p++ = value;
940dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
941dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
942dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid aapolyx(void* con,
943dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLcoord* pts, int count)
944dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
945dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /*
946dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project     * NOTE: This routine assumes that the polygon has been clipped to the
947dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project     * viewport already, that is, no vertex lies outside of the framebuffer.
948dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project     * If this happens, the code below won't corrupt memory but the
949dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project     * coverage values may not be correct.
950dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project     */
951dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
952dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGL_CONTEXT(c, con);
953dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
954dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // we do only quads for now (it's used for thick lines)
955dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if ((count>4) || (count<2)) return;
956dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
957dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // take scissor into account
958dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int xmin = c->state.scissor.left;
959dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int xmax = c->state.scissor.right;
960dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (xmin >= xmax) return;
961dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
962dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // generate edges from the vertices
963dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t ymin = TRI_FROM_INT(c->state.scissor.top);
964dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t ymax = TRI_FROM_INT(c->state.scissor.bottom);
965dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ymin >= ymax) return;
966dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
967dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AAEdge edges[4];
968dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int num_edges = 0;
969dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLcoord const * p = pts;
970dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (int i=0 ; i<count-1 ; i++, p+=2) {
971dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        aa_edge_setup(edges, &num_edges, p, p+2, ymin, ymax);
972dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
973dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    aa_edge_setup(edges, &num_edges, p, pts, ymin, ymax );
974dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ggl_unlikely(num_edges<2))
975dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
976dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
977dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // sort the edge list top to bottom, left to right.
978dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    qsort(edges, num_edges, sizeof(AAEdge), (compar_t)compare_edges);
979dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
980dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int16_t* const covPtr = c->state.buffers.coverage;
981dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(covPtr+xmin, 0, (xmax-xmin)*sizeof(*covPtr));
982dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
983dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // now, sweep all edges in order
984dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // start with the 2 first edges. We know that they share their top
985dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // vertex, by construction.
986dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i = 2;
987dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AAEdge* left  = &edges[0];
988dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AAEdge* right = &edges[1];
989dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int32_t yt = left->y_top;
990dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLfixed l = left->x;
991dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GGLfixed r = right->x;
992dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int retire = 0;
993dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int16_t* coverage;
994dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
995dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // at this point we can initialize the rasterizer
996dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    c->init_y(c, yt>>TRI_FRACTION_BITS);
997dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    c->iterators.xl = xmax;
998dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    c->iterators.xr = xmin;
999dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1000dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do {
1001dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int32_t y = min(min(left->y_bot, right->y_bot), TRI_FLOOR(yt + TRI_ONE));
1002dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const int32_t shift = TRI_FRACTION_BITS + TRI_ITERATORS_BITS - FIXED_BITS;
1003dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const int cf_shift = (1 + TRI_FRACTION_BITS*2 + TRI_ITERATORS_BITS - 15);
1004dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1005dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // compute xmin and xmax for the left edge
1006dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        GGLfixed l_min = gglMulAddx(left->x_incr, y - left->y_top, left->x, shift);
1007dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        GGLfixed l_max = l;
1008dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        l = l_min;
1009dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (l_min > l_max)
1010dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            swap(l_min, l_max);
1011dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1012dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // compute xmin and xmax for the right edge
1013dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        GGLfixed r_min = gglMulAddx(right->x_incr, y - right->y_top, right->x, shift);
1014dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        GGLfixed r_max = r;
1015dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        r = r_min;
1016dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (r_min > r_max)
1017dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            swap(r_min, r_max);
1018dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1019dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // make sure we're not touching coverage values outside of the
1020dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // framebuffer
1021dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        l_min &= ~(l_min>>31);
1022dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        r_min &= ~(r_min>>31);
1023dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        l_max &= ~(l_max>>31);
1024dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        r_max &= ~(r_max>>31);
1025dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (gglFixedToIntFloor(l_min) >= xmax) l_min = gglIntToFixed(xmax)-1;
1026dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (gglFixedToIntFloor(r_min) >= xmax) r_min = gglIntToFixed(xmax)-1;
1027dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (gglFixedToIntCeil(l_max) >= xmax)  l_max = gglIntToFixed(xmax)-1;
1028dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (gglFixedToIntCeil(r_max) >= xmax)  r_max = gglIntToFixed(xmax)-1;
1029dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1030dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // compute the integer versions of the above
1031dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLfixed l_min_i = gglFloorx(l_min);
1032dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLfixed l_max_i = gglCeilx (l_max);
1033dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLfixed r_min_i = gglFloorx(r_min);
1034dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const GGLfixed r_max_i = gglCeilx (r_max);
1035dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1036dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // clip horizontally using the scissor
1037dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const int xml = max(xmin, gglFixedToIntFloor(l_min_i));
1038dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const int xmr = min(xmax, gglFixedToIntFloor(r_max_i));
1039dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1040dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // if we just stepped to a new scanline, render the previous one.
1041dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // and clear the coverage buffer
1042dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (retire) {
1043dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (c->iterators.xl < c->iterators.xr)
1044dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                c->scanline(c);
1045dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c->step_y(c);
1046dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            memset(covPtr+xmin, 0, (xmax-xmin)*sizeof(*covPtr));
1047dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c->iterators.xl = xml;
1048dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c->iterators.xr = xmr;
1049dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
1050dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // update the horizontal range of this scanline
1051dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c->iterators.xl = min(c->iterators.xl, xml);
1052dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            c->iterators.xr = max(c->iterators.xr, xmr);
1053dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
1054dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1055dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        coverage = covPtr + gglFixedToIntFloor(l_min_i);
1056dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (l_min_i == gglFloorx(l_max)) {
1057dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1058dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /*
1059dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             *  fully traverse this pixel vertically
1060dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             *       l_max
1061dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             *  +-----/--+  yt
1062dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             *  |    /   |
1063dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             *  |   /    |
1064dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             *  |  /     |
1065dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             *  +-/------+  y
1066dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             *   l_min  (l_min_i + TRI_ONE)
1067dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             */
1068dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1069dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            GGLfixed dx = l_max - l_min;
1070dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int32_t dy = y - yt;
1071dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int cf = gglMulx((dx >> 1) + (l_min_i + FIXED_ONE - l_max), dy,
1072dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                FIXED_BITS + TRI_FRACTION_BITS - 15);
1073dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD_COVERAGE(coverage, cf);
1074dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // all pixels on the right have cf = 1.0
1075dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
1076dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /*
1077dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             *  spans several pixels in one scanline
1078dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             *            l_max
1079dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             *  +--------+--/-----+  yt
1080dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             *  |        |/       |
1081dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             *  |       /|        |
1082dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             *  |     /  |        |
1083dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             *  +---/----+--------+  y
1084dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             *   l_min (l_min_i + TRI_ONE)
1085dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project             */
1086dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1087dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // handle the first pixel separately...
1088dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            const int32_t y_incr = left->y_incr;
1089dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int32_t dx = TRI_FROM_FIXED(l_min_i - l_min) + TRI_ONE;
1090dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int32_t cf = (dx * dx * y_incr) >> cf_shift;
1091dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD_COVERAGE(coverage, cf);
1092dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1093dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // following pixels get covered by y_incr, but we need
1094dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // to fix-up the cf to account for previous partial pixel
1095dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            dx = TRI_FROM_FIXED(l_min - l_min_i);
1096dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            cf -= (dx * dx * y_incr) >> cf_shift;
1097dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (int x = l_min_i+FIXED_ONE ; x < l_max_i-FIXED_ONE ; x += FIXED_ONE) {
1098dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                cf += y_incr >> (TRI_ITERATORS_BITS-15);
1099dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                ADD_COVERAGE(coverage, cf);
1100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
1101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // and the last pixel
1103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            dx = TRI_FROM_FIXED(l_max - l_max_i) - TRI_ONE;
1104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            cf += (dx * dx * y_incr) >> cf_shift;
1105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ADD_COVERAGE(coverage, cf);
1106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
1107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // now, fill up all fully covered pixels
1109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        coverage = covPtr + gglFixedToIntFloor(l_max_i);
1110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int cf = ((y - yt) << (15 - TRI_FRACTION_BITS));
1111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (ggl_likely(cf >= 0x8000)) {
1112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            SET_COVERAGE(coverage, 0x7FFF, ((r_max - l_max_i)>>FIXED_BITS)+1);
1113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
1114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (int x=l_max_i ; x<r_max ; x+=FIXED_ONE) {
1115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                ADD_COVERAGE(coverage, cf);
1116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
1117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
1118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // subtract the coverage of the right edge
1120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        coverage = covPtr + gglFixedToIntFloor(r_min_i);
1121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (r_min_i == gglFloorx(r_max)) {
1122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            GGLfixed dx = r_max - r_min;
1123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int32_t dy = y - yt;
1124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int cf = gglMulx((dx >> 1) + (r_min_i + FIXED_ONE - r_max), dy,
1125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                FIXED_BITS + TRI_FRACTION_BITS - 15);
1126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            SUB_COVERAGE(coverage, cf);
1127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // all pixels on the right have cf = 1.0
1128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
1129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // handle the first pixel separately...
1130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            const int32_t y_incr = right->y_incr;
1131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int32_t dx = TRI_FROM_FIXED(r_min_i - r_min) + TRI_ONE;
1132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int32_t cf = (dx * dx * y_incr) >> cf_shift;
1133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            SUB_COVERAGE(coverage, cf);
1134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // following pixels get covered by y_incr, but we need
1136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // to fix-up the cf to account for previous partial pixel
1137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            dx = TRI_FROM_FIXED(r_min - r_min_i);
1138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            cf -= (dx * dx * y_incr) >> cf_shift;
1139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (int x = r_min_i+FIXED_ONE ; x < r_max_i-FIXED_ONE ; x += FIXED_ONE) {
1140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                cf += y_incr >> (TRI_ITERATORS_BITS-15);
1141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                SUB_COVERAGE(coverage, cf);
1142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
1143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // and the last pixel
1145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            dx = TRI_FROM_FIXED(r_max - r_max_i) - TRI_ONE;
1146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            cf += (dx * dx * y_incr) >> cf_shift;
1147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            SUB_COVERAGE(coverage, cf);
1148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
1149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // did we reach the end of an edge? if so, get a new one.
1151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (y == left->y_bot || y == right->y_bot) {
1152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // bail out if we're done
1153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (i>=num_edges)
1154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
1155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (y == left->y_bot)
1156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                left = &edges[i++];
1157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (y == right->y_bot)
1158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                right = &edges[i++];
1159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
1160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // next scanline
1162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        yt = y;
1163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // did we just finish a scanline?
1165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        retire = (y << (32-TRI_FRACTION_BITS)) == 0;
1166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } while (true);
1167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // render the last scanline
1169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (c->iterators.xl < c->iterators.xr)
1170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        c->scanline(c);
1171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; // namespace android
1174