static inline IntRect computeUnoccludedContentRect(const IntRect& contentRect, const TransformationMatrix& contentSpaceTransform, const IntRect& scissorRect, const Region& occlusion)
{
    if (!contentSpaceTransform.isInvertible())
        return contentRect;

    // Take the enclosingIntRect at each step, as we want to contain any unoccluded partial pixels in the resulting IntRect.
    FloatRect transformedRect = CCMathUtil::mapClippedRect(contentSpaceTransform, FloatRect(contentRect));
    IntRect shrunkRect = rectSubtractRegion(intersection(enclosingIntRect(transformedRect), scissorRect), occlusion);
    IntRect unoccludedRect = enclosingIntRect(CCMathUtil::projectClippedRect(contentSpaceTransform.inverse(), FloatRect(shrunkRect)));
    // The rect back in content space is a bounding box and may extend outside of the original contentRect, so clamp it to the contentRectBounds.
    return intersection(unoccludedRect, contentRect);
}
Example #2
0
static inline IntRect computeUnoccludedContentRect(const IntRect& contentRect, const TransformationMatrix& contentSpaceTransform, const IntRect& scissorRect, const Region& occlusion)
{
    if (!contentSpaceTransform.isInvertible())
        return contentRect;

    FloatRect transformedRect = contentSpaceTransform.mapRect(FloatRect(contentRect));
    // Take the enclosingIntRect at each step, as we want to contain any unoccluded partial pixels in the resulting IntRect.
    IntRect shrunkRect = rectSubtractRegion(intersection(enclosingIntRect(transformedRect), scissorRect), occlusion);
    bool clamped; // FIXME: projectQuad returns invalid results when a point gets clamped. To be fixed in bug https://bugs.webkit.org/show_bug.cgi?id=80806.
    IntRect unoccludedRect = enclosingIntRect(projectQuad(contentSpaceTransform.inverse(), FloatQuad(FloatRect(shrunkRect)), clamped).boundingBox());
    if (clamped)
        return contentRect;
    // The rect back in content space is a bounding box and may extend outside of the original contentRect, so clamp it to the contentRectBounds.
    return intersection(unoccludedRect, contentRect);
}
Example #3
0
void CCQuadCuller::cullOccludedQuads(CCQuadList& quadList, bool haveDamageRect, const FloatRect& damageRect, CCOverdrawCounts* overdrawMetrics)
{
    if (!quadList.size())
        return;

    CCQuadList culledList;
    culledList.reserveCapacity(quadList.size());

    Region opaqueCoverageThusFar;

    for (int i = quadList.size() - 1; i >= 0; --i) {
        CCDrawQuad* drawQuad = quadList[i].get();

        FloatRect floatTransformedRect = drawQuad->quadTransform().mapRect(FloatRect(drawQuad->quadRect()));
        if (haveDamageRect)
            floatTransformedRect.intersect(damageRect);
        // Inflate rect to be tested to stay conservative.
        IntRect transformedQuadRect(enclosingIntRect(floatTransformedRect));

        IntRect transformedVisibleQuadRect = rectSubtractRegion(opaqueCoverageThusFar, transformedQuadRect);
        bool keepQuad = !transformedVisibleQuadRect.isEmpty();

        // See if we can reduce the number of pixels to draw by reducing the size of the draw
        // quad - we do this by changing its visible rect.
        bool didReduceQuadSize = false;
        if (keepQuad) {
            if (transformedVisibleQuadRect != transformedQuadRect && drawQuad->isLayerAxisAlignedIntRect()) {
                drawQuad->setQuadVisibleRect(drawQuad->quadTransform().inverse().mapRect(transformedVisibleQuadRect));
                didReduceQuadSize = true;
            }

            // When adding rect to opaque region, deflate it to stay conservative.
            if (drawQuad->isLayerAxisAlignedIntRect() && !drawQuad->opaqueRect().isEmpty()) {
                FloatRect floatOpaqueRect = drawQuad->quadTransform().mapRect(FloatRect(drawQuad->opaqueRect()));
                opaqueCoverageThusFar.unite(Region(enclosedIntRect(floatOpaqueRect)));
            }

            culledList.append(quadList[i].release());
        }

        if (overdrawMetrics) {
            TRACE_EVENT("CCQuadCuller::cullOccludedQuads_OverdrawMetrics", 0, 0);
            // We compute the area of the transformed quad, as this should be in pixels.
            float area = quadArea(drawQuad->quadTransform().mapQuad(FloatQuad(drawQuad->quadRect())));
            if (keepQuad) {
                if (didReduceQuadSize) {
                    float visibleQuadRectArea = quadArea(drawQuad->quadTransform().mapQuad(FloatQuad(drawQuad->quadVisibleRect())));
                    overdrawMetrics->m_pixelsCulled += area - visibleQuadRectArea;
                    area = visibleQuadRectArea;
                }
                IntRect visibleOpaqueRect(drawQuad->quadVisibleRect());
                visibleOpaqueRect.intersect(drawQuad->opaqueRect());
                FloatQuad visibleOpaqueQuad = drawQuad->quadTransform().mapQuad(FloatQuad(visibleOpaqueRect));
                float opaqueArea = quadArea(visibleOpaqueQuad);
                overdrawMetrics->m_pixelsDrawnOpaque += opaqueArea;
                overdrawMetrics->m_pixelsDrawnTransparent += area - opaqueArea;
            } else
                overdrawMetrics->m_pixelsCulled += area;
        }
    }
    quadList.clear(); // Release anything that remains.

    culledList.reverse();
    quadList.swap(culledList);
}