// repaint columns from col0 to col1. If col1 is -1, repaint all // the way to the right edge of the table. // called by // 1.void Qps::update_table(int col) void HeadedTable::repaintColumns(int col0, int col1) { QRect bvr = body->viewRect(); QRect hvr = head->viewRect(); int x0 = colOffset(col0) - body->xOffset(); if (x0 > hvr.width()) return; if (x0 < 0) x0 = 0; bvr.setLeft(x0); hvr.setLeft(x0); if (col1 >= 0) { int x1 = colOffset(col1) + max_widths[col1] - body->xOffset(); if (x1 < hvr.width()) { hvr.setRight(x1); bvr.setRight(x1); } } head->repaint(hvr); body->repaint(bvr); }
Mat IntegralGradientFilter::applyTo(const Mat& image, Mat& filtered) const { if (image.type() != CV_32SC1) throw invalid_argument("IntegralGradientFilter: the image must be of type CV_32SC1"); filtered.create(rows, cols, CV_8UC2); int width = image.cols - 1; int height = image.rows - 1; int radiusX = std::max(1, cvRound(static_cast<double>(width - 1) / static_cast<double>(cols + 2))); int radiusY = std::max(1, cvRound(static_cast<double>(height - 1) / static_cast<double>(rows + 2))); double spacingX = static_cast<double>(width - 3 * radiusX) / static_cast<double>(cols - 1); double spacingY = static_cast<double>(height - 3 * radiusY) / static_cast<double>(rows - 1); int gradientHalfArea = radiusY * radiusX; int step0 = static_cast<int>(image.step.p[0]); int step1 = static_cast<int>(image.step.p[1]); int offsetY[] = { -radiusY * step0, 0, radiusY * step0, 2 * radiusY * step0 }; int offsetX[] = { -radiusX * step1, 0, radiusX * step1, 2 * radiusX * step1 }; vector<size_t> rowOffset(rows); vector<size_t> colOffset(cols); for (int row = 0; row < rows; ++row) rowOffset[row] = cvRound(radiusY + row * spacingY) * image.step.p[0]; for (int col = 0; col < cols; ++col) colOffset[col] = cvRound(radiusX + col * spacingX) * image.step.p[1]; for (int row = 0; row < rows; ++row) { const uchar* pRow = image.data + rowOffset[row]; Vec2b* gradientValues = filtered.ptr<Vec2b>(row); for (int col = 0; col < cols; ++col) { const uchar* pPoint = pRow + colOffset[col]; Vec2b& gradient = gradientValues[col]; // p1 p2 // p3 p4 p5 p6 // p7 p8 p9 p10 // p11 p12 int p1 = *reinterpret_cast<const int*>(pPoint + offsetY[0] + offsetX[1]); int p2 = *reinterpret_cast<const int*>(pPoint + offsetY[0] + offsetX[2]); int p3 = *reinterpret_cast<const int*>(pPoint + offsetY[1] + offsetX[0]); int p4 = *reinterpret_cast<const int*>(pPoint + offsetY[1] + offsetX[1]); int p5 = *reinterpret_cast<const int*>(pPoint + offsetY[1] + offsetX[2]); int p6 = *reinterpret_cast<const int*>(pPoint + offsetY[1] + offsetX[3]); int p7 = *reinterpret_cast<const int*>(pPoint + offsetY[2] + offsetX[0]); int p8 = *reinterpret_cast<const int*>(pPoint + offsetY[2] + offsetX[1]); int p9 = *reinterpret_cast<const int*>(pPoint + offsetY[2] + offsetX[2]); int p10 = *reinterpret_cast<const int*>(pPoint + offsetY[2] + offsetX[3]); int p11 = *reinterpret_cast<const int*>(pPoint + offsetY[3] + offsetX[1]); int p12 = *reinterpret_cast<const int*>(pPoint + offsetY[3] + offsetX[2]); int top = p1 - p2 - p4 + p5; int bottom = p8 - p9 - p11 + p12; int left = p3 - p4 - p7 + p8; int right = p5 - p6 - p9 + p10; int dx = (right - left) / (2 * gradientHalfArea); int dy = (bottom - top) / (2 * gradientHalfArea); gradient[0] = static_cast<uchar>(dx + 127); gradient[1] = static_cast<uchar>(dy + 127); } } return filtered; }
//Returns true if the triangle is visible bool DepthBuffer::testTriangle2x2(const vec4f& v0,const vec4f& v1,const vec4f& v2){ VecS32 colOffset(0, 1, 0, 1); VecS32 rowOffset(0, 0, 1, 1); vec2i vertex[3]; vertex[0] = vec2i(int32(v0.x),int32(v0.y)); vertex[1] = vec2i(int32(v1.x),int32(v1.y)); vertex[2] = vec2i(int32(v2.x),int32(v2.y)); // Reject the triangle if any of its verts is behind the nearclip plane if(v0.w == 0.0f || v1.w == 0.0f || v2.w == 0.0f) return true; float minZ = std::min(v0.z,std::min(v1.z,v2.z)); VecF32 fixedDepth(minZ); // Fab(x, y) = Ax + By + C = 0 // Fab(x, y) = (ya - yb)x + (xb - xa)y + (xa * yb - xb * ya) = 0 // Compute A = (ya - yb) for the 3 line segments that make up each triangle auto A0 = vertex[1].y - vertex[2].y; auto A1 = vertex[2].y - vertex[0].y; auto A2 = vertex[0].y - vertex[1].y; // Compute B = (xb - xa) for the 3 line segments that make up each triangle auto B0 = vertex[2].x - vertex[1].x; auto B1 = vertex[0].x - vertex[2].x; auto B2 = vertex[1].x - vertex[0].x; // Compute C = (xa * yb - xb * ya) for the 3 line segments that make up each triangle auto C0 = vertex[1].x * vertex[2].y - vertex[2].x * vertex[1].y; auto C1 = vertex[2].x * vertex[0].y - vertex[0].x * vertex[2].y; auto C2 = vertex[0].x * vertex[1].y - vertex[1].x * vertex[0].y; // Use bounding box traversal strategy to determine which pixels to rasterize auto minx = std::max(std::min(std::min(vertex[0].x,vertex[1].x),vertex[2].x),0) & (~1); auto maxx = std::min(std::max(std::max(vertex[0].x,vertex[1].x),vertex[2].x),size_.x-2); auto miny = std::max(std::min(std::min(vertex[0].y,vertex[1].y),vertex[2].y),0) & (~1); auto maxy = std::min(std::max(std::max(vertex[0].y,vertex[1].y),vertex[2].y),size_.y-2); VecS32 a0(A0); VecS32 a1(A1); VecS32 a2(A2); VecS32 b0(B0); VecS32 b1(B1); VecS32 b2(B2); VecS32 col = VecS32(minx) + colOffset; VecS32 row = VecS32(miny) + rowOffset; auto rowIdx = miny*size_.x + 2 * minx; VecS32 w0_row = a0 * col + b0 * row + VecS32(C0); VecS32 w1_row = a1 * col + b1 * row + VecS32(C1); VecS32 w2_row = a2 * col + b2 * row + VecS32(C2); //Multiply each weight by two(rasterize 2x2 quad at once). a0 = shiftl<1>(a0); a1 = shiftl<1>(a1); a2 = shiftl<1>(a2); b0 = shiftl<1>(b0); b1 = shiftl<1>(b1); b2 = shiftl<1>(b2); for(int32 y = miny;y<=maxy;y+=2,rowIdx += 2 * size_.x){ auto w0 = w0_row; auto w1 = w1_row; auto w2 = w2_row; auto idx = rowIdx; for(int32 x = minx;x<=maxx;x+=2,idx+=4){ auto mask = w0|w1|w2; auto masks = _mm_movemask_ps(bits2float(mask).simd); if(masks != 0xF){ VecF32 previousDepth = VecF32::load(data_+idx); auto cmpMask = ((~masks)&0xF)& _mm_movemask_ps(cmple(fixedDepth,previousDepth).simd); if(cmpMask){ return true; } } w0+=a0; w1+=a1; w2+=a2; } w0_row += b0; w1_row += b1; w2_row += b2; } return false; }
//Rasterize 4 pixels at once void DepthBuffer::rasterizeTile2x2(int32 x,int32 y,uint32 pass) { auto tileIndex = x + y*tileCount_.x; auto count = tileTriangleCount_[tileIndex]; tileTriangleCount_[tileIndex] = 0; auto faces = triangleBins_ + x*kMaxTrianglesPerTile + y*tileCount_.x*kMaxTrianglesPerTile; vec2i tilePos(x*tileSize_.x,y*tileSize_.y); vec2i tileEnd(tilePos + tileSize_); #ifdef ARPHEG_ARCH_X86 enum { kNumLanes = 4 }; //Flush denormals to zero _mm_setcsr( _mm_getcsr() | 0x8040 ); VecS32 colOffset(0, 1, 0, 1); VecS32 rowOffset(0, 0, 1, 1); //Process the 4 binned triangles at a time VecS32 vertexX[3]; VecS32 vertexY[3]; VecF32 vertexZ[4]; VecS32 tileMinXSimd(tilePos.x); VecS32 tileMaxXSimd(tilePos.x+tileSize_.x-2); VecS32 tileMinYSimd(tilePos.y); VecS32 tileMaxYSimd(tilePos.y+tileSize_.y-2); for(uint32 i = 0;i<count;i += kNumLanes){ uint32 numSimdTris = std::min(uint32(kNumLanes),count-i); auto f = faces+i; for(uint32 ii = 0;ii< numSimdTris;++ii){ vertexX[0].lane[ii] = f[ii].v[0].x; vertexY[0].lane[ii] = f[ii].v[0].y; vertexX[1].lane[ii] = f[ii].v[1].x; vertexY[1].lane[ii] = f[ii].v[1].y; vertexX[2].lane[ii] = f[ii].v[2].x; vertexY[2].lane[ii] = f[ii].v[2].y; vertexZ[ii] = VecF32(f[ii].z[0],f[ii].z[1],f[ii].z[2],0.0f); } // Fab(x, y) = Ax + By + C = 0 // Fab(x, y) = (ya - yb)x + (xb - xa)y + (xa * yb - xb * ya) = 0 // Compute A = (ya - yb) for the 3 line segments that make up each triangle VecS32 A0 = vertexY[1] - vertexY[2]; VecS32 A1 = vertexY[2] - vertexY[0]; VecS32 A2 = vertexY[0] - vertexY[1]; // Compute B = (xb - xa) for the 3 line segments that make up each triangle VecS32 B0 = vertexX[2] - vertexX[1]; VecS32 B1 = vertexX[0] - vertexX[2]; VecS32 B2 = vertexX[1] - vertexX[0]; // Compute C = (xa * yb - xb * ya) for the 3 line segments that make up each triangle VecS32 C0 = vertexX[1] * vertexY[2] - vertexX[2] * vertexY[1]; VecS32 C1 = vertexX[2] * vertexY[0] - vertexX[0] * vertexY[2]; VecS32 C2 = vertexX[0] * vertexY[1] - vertexX[1] * vertexY[0]; // Use bounding box traversal strategy to determine which pixels to rasterize VecS32 minX = vmax(vmin(vmin(vertexX[0], vertexX[1]), vertexX[2]), tileMinXSimd) & VecS32(~1); VecS32 maxX = vmin(vmax(vmax(vertexX[0], vertexX[1]), vertexX[2]), tileMaxXSimd); VecS32 minY = vmax(vmin(vmin(vertexY[0], vertexY[1]), vertexY[2]), tileMinYSimd) & VecS32(~1); VecS32 maxY = vmin(vmax(vmax(vertexY[0], vertexY[1]), vertexY[2]), tileMaxYSimd); //Rasterize each triangle individually for(uint32 lane = 0;lane < numSimdTris;++lane){ //Rasterize in 2x2 quads. VecF32 zz[3]; zz[0] = VecF32(vertexZ[lane].lane[0]); zz[1] = VecF32(vertexZ[lane].lane[1]); zz[2] = VecF32(vertexZ[lane].lane[2]); VecS32 a0(A0.lane[lane]); VecS32 a1(A1.lane[lane]); VecS32 a2(A2.lane[lane]); VecS32 b0(B0.lane[lane]); VecS32 b1(B1.lane[lane]); VecS32 b2(B2.lane[lane]); int32 minx = minX.lane[lane]; int32 maxx = maxX.lane[lane]; int32 miny = minY.lane[lane]; int32 maxy = maxY.lane[lane]; VecS32 col = VecS32(minx) + colOffset; VecS32 row = VecS32(miny) + rowOffset; auto rowIdx = miny*size_.x + 2 * minx; VecS32 w0_row = a0 * col + b0 * row + VecS32(C0.lane[lane]); VecS32 w1_row = a1 * col + b1 * row + VecS32(C1.lane[lane]); VecS32 w2_row = a2 * col + b2 * row + VecS32(C2.lane[lane]); //Multiply each weight by two(rasterize 2x2 quad at once). a0 = shiftl<1>(a0); a1 = shiftl<1>(a1); a2 = shiftl<1>(a2); b0 = shiftl<1>(b0); b1 = shiftl<1>(b1); b2 = shiftl<1>(b2); VecF32 zInc = itof(a1)*zz[1] + itof(a2)*zz[2]; for(int32 y = miny;y<=maxy;y+=2,rowIdx += 2 * size_.x){ auto w0 = w0_row; auto w1 = w1_row; auto w2 = w2_row; VecF32 depth = zz[0] + itof(w1)*zz[1] + itof(w2)*zz[2]; auto idx = rowIdx; for(int32 x = minx;x<=maxx;x+=2,idx+=4){ auto mask = w0|w1|w2; VecF32 previousDepth = VecF32::load(data_+idx); VecF32 mergedDepth = vmin(depth,previousDepth); previousDepth = select(mergedDepth,previousDepth,mask); previousDepth.store(data_+idx); w0+=a0; w1+=a1; w2+=a2; depth+=zInc; } w0_row += b0; w1_row += b1; w2_row += b2; } } } #endif }
void DepthBuffer::rasterizeTile(int32 x,int32 y,uint32 pass) { if(pass == 0){ //init tile(clear depth). //auto tilePixels = data_ + x*tileSize_.x*tileSize_.y + (y*tileSize_.x*tileSize_.y)*tileCount_.x; //clearDepth(tilePixels,tileSize_.x*tileSize_.y,1.0f); } if(mode_ == kModeDepthPackedQuads){ rasterizeTile2x2(x,y,pass); return; } auto tileIndex = x + y*tileCount_.x; auto count = tileTriangleCount_[tileIndex]; tileTriangleCount_[tileIndex] = 0; auto faces = triangleBins_ + x*kMaxTrianglesPerTile + y*tileCount_.x*kMaxTrianglesPerTile; vec2i tilePos(x*tileSize_.x,y*tileSize_.y); vec2i tileEnd(tilePos + tileSize_); #ifdef ARPHEG_ARCH_X86 enum { kNumLanes = 4 }; //Flush denormals to zero //_mm_setcsr( _mm_getcsr() | 0x8040 ); VecS32 colOffset(0, 1, 0, 1); VecS32 rowOffset(0, 0, 1, 1); //Process the 4 binned triangles at a time VecS32 vertexX[3]; VecS32 vertexY[3]; VecF32 vertexZ[4]; VecS32 tileMinXSimd(tilePos.x); VecS32 tileMaxXSimd(tilePos.x+tileSize_.x-1); VecS32 tileMinYSimd(tilePos.y); VecS32 tileMaxYSimd(tilePos.y+tileSize_.y-1); for(uint32 i = 0;i<count;i += kNumLanes){ uint32 numSimdTris = std::min(uint32(kNumLanes),count-i); auto f = faces+i; for(uint32 ii = 0;ii< numSimdTris;++ii){ vertexX[0].lane[ii] = f[ii].v[0].x; vertexY[0].lane[ii] = f[ii].v[0].y; vertexX[1].lane[ii] = f[ii].v[1].x; vertexY[1].lane[ii] = f[ii].v[1].y; vertexX[2].lane[ii] = f[ii].v[2].x; vertexY[2].lane[ii] = f[ii].v[2].y; vertexZ[ii] = VecF32(f[ii].z[0],f[ii].z[1],f[ii].z[2],0.0f); } // Fab(x, y) = Ax + By + C = 0 // Fab(x, y) = (ya - yb)x + (xb - xa)y + (xa * yb - xb * ya) = 0 // Compute A = (ya - yb) for the 3 line segments that make up each triangle VecS32 A0 = vertexY[1] - vertexY[2]; VecS32 A1 = vertexY[2] - vertexY[0]; VecS32 A2 = vertexY[0] - vertexY[1]; // Compute B = (xb - xa) for the 3 line segments that make up each triangle VecS32 B0 = vertexX[2] - vertexX[1]; VecS32 B1 = vertexX[0] - vertexX[2]; VecS32 B2 = vertexX[1] - vertexX[0]; // Compute C = (xa * yb - xb * ya) for the 3 line segments that make up each triangle VecS32 C0 = vertexX[1] * vertexY[2] - vertexX[2] * vertexY[1]; VecS32 C1 = vertexX[2] * vertexY[0] - vertexX[0] * vertexY[2]; VecS32 C2 = vertexX[0] * vertexY[1] - vertexX[1] * vertexY[0]; // Use bounding box traversal strategy to determine which pixels to rasterize VecS32 minX = vmax(vmin(vmin(vertexX[0], vertexX[1]), vertexX[2]), tileMinXSimd); VecS32 maxX = vmin(vmax(vmax(vertexX[0], vertexX[1]), vertexX[2]), tileMaxXSimd); VecS32 minY = vmax(vmin(vmin(vertexY[0], vertexY[1]), vertexY[2]), tileMinYSimd); VecS32 maxY = vmin(vmax(vmax(vertexY[0], vertexY[1]), vertexY[2]), tileMaxYSimd); //Rasterize each triangle individually for(uint32 lane = 0;lane < numSimdTris;++lane){ float zz[3] = { vertexZ[lane].lane[0],vertexZ[lane].lane[1],vertexZ[lane].lane[2] }; int32 a0 = A0.lane[lane]; int32 a1 = A1.lane[lane]; int32 a2 = A2.lane[lane]; int32 b0 = B0.lane[lane]; int32 b1 = B1.lane[lane]; int32 b2 = B2.lane[lane]; int32 minx = minX.lane[lane]; int32 maxx = maxX.lane[lane]; int32 miny = minY.lane[lane]; int32 maxy = maxY.lane[lane]; auto w0_row = a0 * minx + b0 * miny + C0.lane[lane]; auto w1_row = a1 * minx + b1 * miny + C1.lane[lane]; auto w2_row = a2 * minx + b2 * miny + C2.lane[lane]; float* tilePixels = data_ + tilePos.x*tileSize_.y + (tilePos.y*tileSize_.x)*tileCount_.x; int32 idx2 = minx-tilePos.x + (miny - tilePos.y)*tileSize_.x; int32 spanx = maxx-minx; for(int32 endIdx2 = idx2+(tileSize_.x)*(maxy-miny);idx2<=endIdx2;idx2+=tileSize_.x){ auto w0 = w0_row; auto w1 = w1_row; auto w2 = w2_row; auto idx = idx2; for(int32 endIdx = idx+spanx;idx<=endIdx;++idx){ auto mask = w0|w1|w2; if(mask >= 0){ float betaf = float(w1); float gamaf = float(w2); float depth = zz[0] + betaf*zz[1] + gamaf*zz[2]; auto d = tilePixels[idx]; d = depth<d?depth:d; tilePixels[idx] = d; } w0+=a0; w1+=a1; w2+=a2; } w0_row += b0; w1_row += b1; w2_row += b2; } } } #else for(uint32 i = 0;i<count;i ++){ drawTriangle(faces[i],tilePos); } #endif }