/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #ifndef GFX_SRC_NSRECTINTERSECTGENERICIMPL_H_ #define GFX_SRC_NSRECTINTERSECTGENERICIMPL_H_ #include "nsRectIntersectGeneric.h" #include template void mozilla::IntersectEngine::Intersect(const int32_t lhs[4], const int32_t rhs[4], int32_t result[4]) { using batch_type = xsimd::batch; static_assert(batch_type::size == 4, "Algorithm tied to 128 bits registers"); auto rect1 = batch_type::load_unaligned(lhs); // x1, y1, w1, h1 auto rect2 = batch_type::load_unaligned(rhs); // x2, y2, w2, h2 auto resultRect = xsimd::max(rect1, rect2); // xr, yr, zz, zz // result.width = std::min(x - result.x + width, // aRect.x - result.x + aRect.width); // result.height = std::min(y - result.y + height, // aRect.y - result.y + aRect.height); auto widthheight = xsimd::min( rect1 - resultRect + xsimd::slide_right<8>(rect1), rect2 - resultRect + xsimd::slide_right<8>(rect2)); // w, h, zz, zz widthheight = xsimd::slide_left<8>(widthheight); // 00, 00, wr, hr constexpr xsimd::batch_bool_constant mask; resultRect = xsimd::select(mask, resultRect, widthheight); // xr, yr, wr, hr if (((resultRect < 0).mask() & 0xC) != 0) { // It's potentially more efficient to store all 0s. But the non vectorized // code leaves x/y intact so let's do the same here. resultRect = resultRect & xsimd::batch{-1, -1, 0, 0}; } resultRect.store_unaligned(result); } template bool mozilla::IntersectEngine::IntersectRect(const int32_t lhs[4], const int32_t rhs[4], int32_t result[4]) { using batch_type = xsimd::batch; static_assert(batch_type::size == 4, "Algorithm tied to 128 bits registers"); auto rect1 = batch_type::load_unaligned(lhs); // x1, y1, w1, h1 auto rect2 = batch_type::load_unaligned(rhs); // x2, y2, w2, h2 auto resultRect = xsimd::max(rect1, rect2); // xr, yr, zz, zz // result.width = std::min(x - result.x + width, // aRect.x - result.x + aRect.width); // result.height = std::min(y - result.y + height, // aRect.y - result.y + aRect.height); auto widthheight = xsimd::min( rect1 - resultRect + xsimd::slide_right<8>(rect1), rect2 - resultRect + xsimd::slide_right<8>(rect2)); // w, h, zz, zz widthheight = xsimd::slide_left<8>(widthheight); // 00, 00, wr, hr constexpr xsimd::batch_bool_constant mask; resultRect = xsimd::select(mask, resultRect, widthheight); // xr, yr, wr, hr const bool isDisjoint = ((resultRect > 0).mask() & 0xC) != 0xC; if (isDisjoint) { // It's potentially more efficient to store all 0s. But the non vectorized // code leaves x/y intact so let's do the same here. resultRect = resultRect & xsimd::batch{-1, -1, 0, 0}; } resultRect.store_unaligned(result); return !isDisjoint; } #endif // GFX_SRC_NSRECTINTERSECTGENERICIMPL_H_