📄 trap.cpp
字号:
/* libs/pixelflinger/trap.cpp**** Copyright 2006, The Android Open Source Project**** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at **** http://www.apache.org/licenses/LICENSE-2.0 **** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License.*/#include <assert.h>#include <stdio.h>#include <stdlib.h>#include "trap.h"#include "picker.h"#include <cutils/log.h>#include <cutils/memory.h>namespace android {// ----------------------------------------------------------------------------// enable to see triangles edges#define DEBUG_TRANGLES 0// ----------------------------------------------------------------------------static void pointx_validate(void *con, const GGLcoord* c, GGLcoord r);static void pointx(void *con, const GGLcoord* c, GGLcoord r);static void aa_pointx(void *con, const GGLcoord* c, GGLcoord r);static void aa_nice_pointx(void *con, const GGLcoord* c, GGLcoord r);static void linex_validate(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord w);static void linex(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord w);static void aa_linex(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord w);static void recti_validate(void* c, GGLint l, GGLint t, GGLint r, GGLint b); static void recti(void* c, GGLint l, GGLint t, GGLint r, GGLint b); static void trianglex_validate(void*, const GGLcoord*, const GGLcoord*, const GGLcoord*);static void trianglex_small(void*, const GGLcoord*, const GGLcoord*, const GGLcoord*);static void trianglex_big(void*, const GGLcoord*, const GGLcoord*, const GGLcoord*);static void aa_trianglex(void*, const GGLcoord*, const GGLcoord*, const GGLcoord*);static void trianglex_debug(void* con, const GGLcoord*, const GGLcoord*, const GGLcoord*);static void aapolyx(void* con, const GGLcoord* pts, int count);static inline int min(int a, int b) CONST;static inline int max(int a, int b) CONST;static inline int min(int a, int b, int c) CONST;static inline int max(int a, int b, int c) CONST;// ----------------------------------------------------------------------------#if 0#pragma mark -#pragma mark Tools#endifinline int min(int a, int b) { return a<b ? a : b;}inline int max(int a, int b) { return a<b ? b : a;}inline int min(int a, int b, int c) { return min(a,min(b,c));}inline int max(int a, int b, int c) { return max(a,max(b,c));}template <typename T>static inline void swap(T& a, T& b) { T t(a); a = b; b = t;}static voidtriangle_dump_points( const GGLcoord* v0, const GGLcoord* v1, const GGLcoord* v2 ){ float tri = 1.0f / TRI_ONE; LOGD( " P0=(%.3f, %.3f) [%08x, %08x]\n" " P1=(%.3f, %.3f) [%08x, %08x]\n" " P2=(%.3f, %.3f) [%08x, %08x]\n", v0[0]*tri, v0[1]*tri, v0[0], v0[1], v1[0]*tri, v1[1]*tri, v1[0], v1[1], v2[0]*tri, v2[1]*tri, v2[0], v2[1] );}// ----------------------------------------------------------------------------#if 0#pragma mark -#pragma mark Misc#endifvoid ggl_init_trap(context_t* c){ ggl_state_changed(c, GGL_PIXEL_PIPELINE_STATE|GGL_TMU_STATE|GGL_CB_STATE);}void ggl_state_changed(context_t* c, int flags){ if (ggl_likely(!c->dirty)) { c->procs.pointx = pointx_validate; c->procs.linex = linex_validate; c->procs.recti = recti_validate; c->procs.trianglex = trianglex_validate; } c->dirty |= uint32_t(flags);}// ----------------------------------------------------------------------------#if 0#pragma mark -#pragma mark Point#endifvoid pointx_validate(void *con, const GGLcoord* v, GGLcoord rad){ GGL_CONTEXT(c, con); ggl_pick(c); if (c->state.needs.p & GGL_NEED_MASK(P_AA)) { if (c->state.enables & GGL_ENABLE_POINT_AA_NICE) { c->procs.pointx = aa_nice_pointx; } else { c->procs.pointx = aa_pointx; } } else { c->procs.pointx = pointx; } c->procs.pointx(con, v, rad);}void pointx(void *con, const GGLcoord* v, GGLcoord rad){ GGL_CONTEXT(c, con); GGLcoord halfSize = TRI_ROUND(rad) >> 1; if (halfSize == 0) halfSize = TRI_HALF; GGLcoord xc = v[0]; GGLcoord yc = v[1]; if (halfSize & TRI_HALF) { // size odd xc = TRI_FLOOR(xc) + TRI_HALF; yc = TRI_FLOOR(yc) + TRI_HALF; } else { // size even xc = TRI_ROUND(xc); yc = TRI_ROUND(yc); } GGLint l = (xc - halfSize) >> TRI_FRACTION_BITS; GGLint t = (yc - halfSize) >> TRI_FRACTION_BITS; GGLint r = (xc + halfSize) >> TRI_FRACTION_BITS; GGLint b = (yc + halfSize) >> TRI_FRACTION_BITS; recti(c, l, t, r, b);}// This way of computing the coverage factor, is more accurate and gives// better results for small circles, but it is also a lot slower.// Here we use super-sampling.static int32_t coverageNice(GGLcoord x, GGLcoord y, GGLcoord rmin, GGLcoord rmax, GGLcoord rr){ const GGLcoord d2 = x*x + y*y; if (d2 >= rmax) return 0; if (d2 < rmin) return 0x7FFF; const int kSamples = 4; const int kInc = 4; // 1/4 = 0.25 const int kCoverageUnit = 1; // 1/(4^2) = 0.0625 const GGLcoord kCoordOffset = -6; // -0.375 int hits = 0; int x_sample = x + kCoordOffset; for (int i=0 ; i<kSamples ; i++, x_sample += kInc) { const int xval = rr - (x_sample * x_sample); int y_sample = y + kCoordOffset; for (int j=0 ; j<kSamples ; j++, y_sample += kInc) { if (xval - (y_sample * y_sample) > 0) hits += kCoverageUnit; } } return min(0x7FFF, hits << (15 - kSamples));}void aa_nice_pointx(void *con, const GGLcoord* v, GGLcoord size){ GGL_CONTEXT(c, con); GGLcoord rad = ((size + 1)>>1); GGLint l = (v[0] - rad) >> TRI_FRACTION_BITS; GGLint t = (v[1] - rad) >> TRI_FRACTION_BITS; GGLint r = (v[0] + rad + (TRI_ONE-1)) >> TRI_FRACTION_BITS; GGLint b = (v[1] + rad + (TRI_ONE-1)) >> TRI_FRACTION_BITS; GGLcoord xstart = TRI_FROM_INT(l) - v[0] + TRI_HALF; GGLcoord ystart = TRI_FROM_INT(t) - v[1] + TRI_HALF; // scissor... if (l < GGLint(c->state.scissor.left)) { xstart += TRI_FROM_INT(c->state.scissor.left-l); l = GGLint(c->state.scissor.left); } if (t < GGLint(c->state.scissor.top)) { ystart += TRI_FROM_INT(c->state.scissor.top-t); t = GGLint(c->state.scissor.top); } if (r > GGLint(c->state.scissor.right)) { r = GGLint(c->state.scissor.right); } if (b > GGLint(c->state.scissor.bottom)) { b = GGLint(c->state.scissor.bottom); } int xc = r - l; int yc = b - t; if (xc>0 && yc>0) { int16_t* covPtr = c->state.buffers.coverage; const int32_t sqr2Over2 = 0xC; // rounded up GGLcoord rr = rad*rad; GGLcoord rmin = (rad - sqr2Over2)*(rad - sqr2Over2); GGLcoord rmax = (rad + sqr2Over2)*(rad + sqr2Over2); GGLcoord y = ystart; c->iterators.xl = l; c->iterators.xr = r; c->init_y(c, t); do { // compute coverage factors for each pixel GGLcoord x = xstart; for (int i=l ; i<r ; i++) { covPtr[i] = coverageNice(x, y, rmin, rmax, rr); x += TRI_ONE; } y += TRI_ONE; c->scanline(c); c->step_y(c); } while (--yc); }}// This is a cheap way of computing the coverage factor for a circle.// We just lerp between the circles of radii r-sqrt(2)/2 and r+sqrt(2)/2static inline int32_t coverageFast(GGLcoord x, GGLcoord y, GGLcoord rmin, GGLcoord rmax, GGLcoord scale){ const GGLcoord d2 = x*x + y*y; if (d2 >= rmax) return 0; if (d2 < rmin) return 0x7FFF; return 0x7FFF - (d2-rmin)*scale;}void aa_pointx(void *con, const GGLcoord* v, GGLcoord size){ GGL_CONTEXT(c, con); GGLcoord rad = ((size + 1)>>1); GGLint l = (v[0] - rad) >> TRI_FRACTION_BITS; GGLint t = (v[1] - rad) >> TRI_FRACTION_BITS; GGLint r = (v[0] + rad + (TRI_ONE-1)) >> TRI_FRACTION_BITS; GGLint b = (v[1] + rad + (TRI_ONE-1)) >> TRI_FRACTION_BITS; GGLcoord xstart = TRI_FROM_INT(l) - v[0] + TRI_HALF; GGLcoord ystart = TRI_FROM_INT(t) - v[1] + TRI_HALF; // scissor... if (l < GGLint(c->state.scissor.left)) { xstart += TRI_FROM_INT(c->state.scissor.left-l); l = GGLint(c->state.scissor.left); } if (t < GGLint(c->state.scissor.top)) { ystart += TRI_FROM_INT(c->state.scissor.top-t); t = GGLint(c->state.scissor.top); } if (r > GGLint(c->state.scissor.right)) { r = GGLint(c->state.scissor.right); } if (b > GGLint(c->state.scissor.bottom)) { b = GGLint(c->state.scissor.bottom); } int xc = r - l; int yc = b - t; if (xc>0 && yc>0) { int16_t* covPtr = c->state.buffers.coverage; rad <<= 4; const int32_t sqr2Over2 = 0xB5; // fixed-point 24.8 GGLcoord rmin = rad - sqr2Over2; GGLcoord rmax = rad + sqr2Over2; GGLcoord scale; rmin *= rmin; rmax *= rmax; scale = 0x800000 / (rmax - rmin); rmin >>= 8; rmax >>= 8; GGLcoord y = ystart; c->iterators.xl = l; c->iterators.xr = r; c->init_y(c, t); do { // compute coverage factors for each pixel GGLcoord x = xstart; for (int i=l ; i<r ; i++) { covPtr[i] = coverageFast(x, y, rmin, rmax, scale); x += TRI_ONE; } y += TRI_ONE; c->scanline(c); c->step_y(c); } while (--yc); }}// ----------------------------------------------------------------------------#if 0#pragma mark -#pragma mark Line#endifvoid linex_validate(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord w){ GGL_CONTEXT(c, con); ggl_pick(c); if (c->state.needs.p & GGL_NEED_MASK(P_AA)) { c->procs.linex = aa_linex; } else { c->procs.linex = linex; } c->procs.linex(con, v0, v1, w);}static void linex(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord width){ GGL_CONTEXT(c, con); GGLcoord v[4][2]; v[0][0] = v0[0]; v[0][1] = v0[1]; v[1][0] = v1[0]; v[1][1] = v1[1]; v0 = v[0]; v1 = v[1]; const GGLcoord dx = abs(v0[0] - v1[0]); const GGLcoord dy = abs(v0[1] - v1[1]); GGLcoord nx, ny; nx = ny = 0; GGLcoord halfWidth = TRI_ROUND(width) >> 1; if (halfWidth == 0) halfWidth = TRI_HALF; ((dx > dy) ? ny : nx) = halfWidth; v[2][0] = v1[0]; v[2][1] = v1[1]; v[3][0] = v0[0]; v[3][1] = v0[1]; v[0][0] += nx; v[0][1] += ny; v[1][0] += nx; v[1][1] += ny; v[2][0] -= nx; v[2][1] -= ny; v[3][0] -= nx; v[3][1] -= ny; trianglex_big(con, v[0], v[1], v[2]); trianglex_big(con, v[0], v[2], v[3]);}static void aa_linex(void *con, const GGLcoord* v0, const GGLcoord* v1, GGLcoord width){ GGL_CONTEXT(c, con); GGLcoord v[4][2]; v[0][0] = v0[0]; v[0][1] = v0[1]; v[1][0] = v1[0]; v[1][1] = v1[1]; v0 = v[0]; v1 = v[1]; const GGLcoord dx = v0[0] - v1[0]; const GGLcoord dy = v0[1] - v1[1]; GGLcoord nx = -dy; GGLcoord ny = dx; // generally, this will be well below 1.0 const GGLfixed norm = gglMulx(width, gglSqrtRecipx(nx*nx+ny*ny), 4); nx = gglMulx(nx, norm, 21);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -