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); }
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); }
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); }