Loading services/surfaceflinger/BufferLayer.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -665,6 +665,36 @@ uint64_t BufferLayer::getHeadFrameNumber() const { } } Rect BufferLayer::getBufferSize(const State& s) const { // If we have a sideband stream, or we are scaling the buffer then return the layer size since // we cannot determine the buffer size. if ((s.sidebandStream != nullptr) || (getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE)) { return Rect(getActiveWidth(s), getActiveHeight(s)); } if (mActiveBuffer == nullptr) { return Rect::INVALID_RECT; } uint32_t bufWidth = mActiveBuffer->getWidth(); uint32_t bufHeight = mActiveBuffer->getHeight(); // Undo any transformations on the buffer and return the result. if (mCurrentTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } if (getTransformToDisplayInverse()) { uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); if (invTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } } return Rect(bufWidth, bufHeight); } } // namespace android #if defined(__gl_h_) Loading services/surfaceflinger/BufferLayer.h +2 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,8 @@ private: mutable renderengine::Texture mTexture; bool mRefreshPending{false}; Rect getBufferSize(const State& s) const override; }; } // namespace android services/surfaceflinger/BufferStateLayer.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -35,7 +35,9 @@ const std::array<float, 16> BufferStateLayer::IDENTITY_MATRIX{ }; // clang-format on BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args) {} BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args) { mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; } BufferStateLayer::~BufferStateLayer() = default; // ----------------------------------------------------------------------- Loading Loading @@ -447,7 +449,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse } } if (mOverrideScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE && if (getEffectiveScalingMode() == NATIVE_WINDOW_SCALING_MODE_FREEZE && (s.active.w != bufferWidth || s.active.h != bufferHeight)) { ALOGE("[%s] rejecting buffer: " "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}", Loading services/surfaceflinger/Layer.cpp +63 −50 Original line number Diff line number Diff line Loading @@ -275,39 +275,12 @@ static FloatRect reduce(const FloatRect& win, const Region& exclude) { return Region(Rect{win}).subtract(exclude).getBounds().toFloatRect(); } Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { const State& s(getDrawingState()); Rect win(getActiveWidth(s), getActiveHeight(s)); Rect crop = getCrop(s); if (!crop.isEmpty()) { win.intersect(crop, &win); } Rect Layer::computeScreenBounds() const { FloatRect bounds = computeBounds(); ui::Transform t = getTransform(); win = t.transform(win); const sp<Layer>& p = mDrawingParent.promote(); // Now we need to calculate the parent bounds, so we can clip ourselves to those. // When calculating the parent bounds for purposes of clipping, // we don't need to constrain the parent to its transparent region. // The transparent region is an optimization based on the // buffer contents of the layer, but does not affect the space allocated to // it by policy, and thus children should be allowed to extend into the // parent's transparent region. In fact one of the main uses, is to reduce // buffer allocation size in cases where a child window sits behind a main window // (by marking the hole in the parent window as a transparent region) if (p != nullptr) { Rect bounds = p->computeScreenBounds(false); bounds.intersect(win, &win); } if (reduceTransparentRegion) { auto const screenTransparentRegion = t.transform(getActiveTransparentRegion(s)); win = reduce(win, screenTransparentRegion); } return win; // Transform to screen space. bounds = t.transform(bounds); return Rect{bounds}; } FloatRect Layer::computeBounds() const { Loading @@ -317,32 +290,72 @@ FloatRect Layer::computeBounds() const { FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { const State& s(getDrawingState()); Rect win(getActiveWidth(s), getActiveHeight(s)); Rect crop = getCrop(s); if (!crop.isEmpty()) { win.intersect(crop, &win); } Rect bounds = getCroppedBufferSize(s); FloatRect floatBounds = bounds.toFloatRect(); if (bounds.isValid()) { // Layer has bounds. Pass in our bounds as a special case. Then pass on to our parents so // that they can clip it. floatBounds = cropChildBounds(floatBounds); } else { // Layer does not have bounds, so we fill to our parent bounds. This is done by getting our // parent bounds and inverting the transform to get the maximum bounds we can have that // will fit within our parent bounds. const auto& p = mDrawingParent.promote(); FloatRect floatWin = win.toFloatRect(); FloatRect parentBounds = floatWin; if (p != nullptr) { // We pass an empty Region here for reasons mirroring that of the case described in // the computeScreenBounds reduceTransparentRegion=false case. parentBounds = p->computeBounds(Region()); ui::Transform t = s.active_legacy.transform; // When calculating the parent bounds for purposes of clipping, we don't need to // constrain the parent to its transparent region. The transparent region is an // optimization based on the buffer contents of the layer, but does not affect the // space allocated to it by policy, and thus children should be allowed to extend into // the parent's transparent region. // One of the main uses is a parent window with a child sitting behind the parent // window, marked by a transparent region. When computing the parent bounds from the // parent's perspective we pass in the transparent region to reduce buffer allocation // size. When computing the parent bounds from the child's perspective, we pass in an // empty transparent region in order to extend into the the parent bounds. floatBounds = p->computeBounds(Region()); // Transform back to layer space. floatBounds = t.inverse().transform(floatBounds); } } ui::Transform t = s.active_legacy.transform; // Subtract the transparent region and snap to the bounds. return reduce(floatBounds, activeTransparentRegion); } FloatRect Layer::cropChildBounds(const FloatRect& childBounds) const { const State& s(getDrawingState()); Rect bounds = getCroppedBufferSize(s); FloatRect croppedBounds = childBounds; // If the layer has bounds, then crop the passed in child bounds and pass // it to our parents so they can crop it as well. If the layer has no bounds, // then pass on the child bounds. if (bounds.isValid()) { croppedBounds = croppedBounds.intersect(bounds.toFloatRect()); } const auto& p = mDrawingParent.promote(); if (p != nullptr) { floatWin = t.transform(floatWin); floatWin = floatWin.intersect(parentBounds); floatWin = t.inverse().transform(floatWin); // Transform to parent space and allow parent layer to crop the // child bounds as well. ui::Transform t = s.active_legacy.transform; croppedBounds = t.transform(croppedBounds); croppedBounds = p->cropChildBounds(croppedBounds); croppedBounds = t.inverse().transform(croppedBounds); } return croppedBounds; } // subtract the transparent region and snap to the bounds return reduce(floatWin, activeTransparentRegion); Rect Layer::getCroppedBufferSize(const State& s) const { Rect size = getBufferSize(s); Rect crop = getCrop(s); if (!crop.isEmpty() && size.isValid()) { size.intersect(crop, &size); } else if (!crop.isEmpty()) { size = crop; } return size; } Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& display) const { Loading services/surfaceflinger/Layer.h +22 −1 Original line number Diff line number Diff line Loading @@ -579,7 +579,7 @@ public: ssize_t removeChild(const sp<Layer>& layer); sp<Layer> getParent() const { return mCurrentParent.promote(); } bool hasParent() const { return getParent() != nullptr; } Rect computeScreenBounds(bool reduceTransparentRegion = true) const; Rect computeScreenBounds() const; bool setChildLayer(const sp<Layer>& childLayer, int32_t z); bool setChildRelativeLayer(const sp<Layer>& childLayer, const sp<IBinder>& relativeToHandle, int32_t relativeZ); Loading Loading @@ -791,6 +791,27 @@ private: const LayerVector::Visitor& visitor); LayerVector makeChildrenTraversalList(LayerVector::StateSet stateSet, const std::vector<Layer*>& layersInTree); /** * Retuns the child bounds in layer space cropped to its bounds as well all its parent bounds. * The cropped bounds must be transformed back from parent layer space to child layer space by * applying the inverse of the child's transformation. */ FloatRect cropChildBounds(const FloatRect& childBounds) const; /** * Returns the cropped buffer size or the layer crop if the layer has no buffer. Return * INVALID_RECT if the layer has no buffer and no crop. * A layer with an invalid buffer size and no crop is considered to be boundless. The layer * bounds are constrained by its parent bounds. */ Rect getCroppedBufferSize(const Layer::State& s) const; /** * Returns active buffer size in the correct orientation. Buffer size is determined by undoing * any buffer transformations. If the layer has no buffer then return INVALID_RECT. */ virtual Rect getBufferSize(const Layer::State&) const { return Rect::INVALID_RECT; } }; // --------------------------------------------------------------------------- Loading Loading
services/surfaceflinger/BufferLayer.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -665,6 +665,36 @@ uint64_t BufferLayer::getHeadFrameNumber() const { } } Rect BufferLayer::getBufferSize(const State& s) const { // If we have a sideband stream, or we are scaling the buffer then return the layer size since // we cannot determine the buffer size. if ((s.sidebandStream != nullptr) || (getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE)) { return Rect(getActiveWidth(s), getActiveHeight(s)); } if (mActiveBuffer == nullptr) { return Rect::INVALID_RECT; } uint32_t bufWidth = mActiveBuffer->getWidth(); uint32_t bufHeight = mActiveBuffer->getHeight(); // Undo any transformations on the buffer and return the result. if (mCurrentTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } if (getTransformToDisplayInverse()) { uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform(); if (invTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } } return Rect(bufWidth, bufHeight); } } // namespace android #if defined(__gl_h_) Loading
services/surfaceflinger/BufferLayer.h +2 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,8 @@ private: mutable renderengine::Texture mTexture; bool mRefreshPending{false}; Rect getBufferSize(const State& s) const override; }; } // namespace android
services/surfaceflinger/BufferStateLayer.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -35,7 +35,9 @@ const std::array<float, 16> BufferStateLayer::IDENTITY_MATRIX{ }; // clang-format on BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args) {} BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args) { mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; } BufferStateLayer::~BufferStateLayer() = default; // ----------------------------------------------------------------------- Loading Loading @@ -447,7 +449,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse } } if (mOverrideScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE && if (getEffectiveScalingMode() == NATIVE_WINDOW_SCALING_MODE_FREEZE && (s.active.w != bufferWidth || s.active.h != bufferHeight)) { ALOGE("[%s] rejecting buffer: " "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}", Loading
services/surfaceflinger/Layer.cpp +63 −50 Original line number Diff line number Diff line Loading @@ -275,39 +275,12 @@ static FloatRect reduce(const FloatRect& win, const Region& exclude) { return Region(Rect{win}).subtract(exclude).getBounds().toFloatRect(); } Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { const State& s(getDrawingState()); Rect win(getActiveWidth(s), getActiveHeight(s)); Rect crop = getCrop(s); if (!crop.isEmpty()) { win.intersect(crop, &win); } Rect Layer::computeScreenBounds() const { FloatRect bounds = computeBounds(); ui::Transform t = getTransform(); win = t.transform(win); const sp<Layer>& p = mDrawingParent.promote(); // Now we need to calculate the parent bounds, so we can clip ourselves to those. // When calculating the parent bounds for purposes of clipping, // we don't need to constrain the parent to its transparent region. // The transparent region is an optimization based on the // buffer contents of the layer, but does not affect the space allocated to // it by policy, and thus children should be allowed to extend into the // parent's transparent region. In fact one of the main uses, is to reduce // buffer allocation size in cases where a child window sits behind a main window // (by marking the hole in the parent window as a transparent region) if (p != nullptr) { Rect bounds = p->computeScreenBounds(false); bounds.intersect(win, &win); } if (reduceTransparentRegion) { auto const screenTransparentRegion = t.transform(getActiveTransparentRegion(s)); win = reduce(win, screenTransparentRegion); } return win; // Transform to screen space. bounds = t.transform(bounds); return Rect{bounds}; } FloatRect Layer::computeBounds() const { Loading @@ -317,32 +290,72 @@ FloatRect Layer::computeBounds() const { FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const { const State& s(getDrawingState()); Rect win(getActiveWidth(s), getActiveHeight(s)); Rect crop = getCrop(s); if (!crop.isEmpty()) { win.intersect(crop, &win); } Rect bounds = getCroppedBufferSize(s); FloatRect floatBounds = bounds.toFloatRect(); if (bounds.isValid()) { // Layer has bounds. Pass in our bounds as a special case. Then pass on to our parents so // that they can clip it. floatBounds = cropChildBounds(floatBounds); } else { // Layer does not have bounds, so we fill to our parent bounds. This is done by getting our // parent bounds and inverting the transform to get the maximum bounds we can have that // will fit within our parent bounds. const auto& p = mDrawingParent.promote(); FloatRect floatWin = win.toFloatRect(); FloatRect parentBounds = floatWin; if (p != nullptr) { // We pass an empty Region here for reasons mirroring that of the case described in // the computeScreenBounds reduceTransparentRegion=false case. parentBounds = p->computeBounds(Region()); ui::Transform t = s.active_legacy.transform; // When calculating the parent bounds for purposes of clipping, we don't need to // constrain the parent to its transparent region. The transparent region is an // optimization based on the buffer contents of the layer, but does not affect the // space allocated to it by policy, and thus children should be allowed to extend into // the parent's transparent region. // One of the main uses is a parent window with a child sitting behind the parent // window, marked by a transparent region. When computing the parent bounds from the // parent's perspective we pass in the transparent region to reduce buffer allocation // size. When computing the parent bounds from the child's perspective, we pass in an // empty transparent region in order to extend into the the parent bounds. floatBounds = p->computeBounds(Region()); // Transform back to layer space. floatBounds = t.inverse().transform(floatBounds); } } ui::Transform t = s.active_legacy.transform; // Subtract the transparent region and snap to the bounds. return reduce(floatBounds, activeTransparentRegion); } FloatRect Layer::cropChildBounds(const FloatRect& childBounds) const { const State& s(getDrawingState()); Rect bounds = getCroppedBufferSize(s); FloatRect croppedBounds = childBounds; // If the layer has bounds, then crop the passed in child bounds and pass // it to our parents so they can crop it as well. If the layer has no bounds, // then pass on the child bounds. if (bounds.isValid()) { croppedBounds = croppedBounds.intersect(bounds.toFloatRect()); } const auto& p = mDrawingParent.promote(); if (p != nullptr) { floatWin = t.transform(floatWin); floatWin = floatWin.intersect(parentBounds); floatWin = t.inverse().transform(floatWin); // Transform to parent space and allow parent layer to crop the // child bounds as well. ui::Transform t = s.active_legacy.transform; croppedBounds = t.transform(croppedBounds); croppedBounds = p->cropChildBounds(croppedBounds); croppedBounds = t.inverse().transform(croppedBounds); } return croppedBounds; } // subtract the transparent region and snap to the bounds return reduce(floatWin, activeTransparentRegion); Rect Layer::getCroppedBufferSize(const State& s) const { Rect size = getBufferSize(s); Rect crop = getCrop(s); if (!crop.isEmpty() && size.isValid()) { size.intersect(crop, &size); } else if (!crop.isEmpty()) { size = crop; } return size; } Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& display) const { Loading
services/surfaceflinger/Layer.h +22 −1 Original line number Diff line number Diff line Loading @@ -579,7 +579,7 @@ public: ssize_t removeChild(const sp<Layer>& layer); sp<Layer> getParent() const { return mCurrentParent.promote(); } bool hasParent() const { return getParent() != nullptr; } Rect computeScreenBounds(bool reduceTransparentRegion = true) const; Rect computeScreenBounds() const; bool setChildLayer(const sp<Layer>& childLayer, int32_t z); bool setChildRelativeLayer(const sp<Layer>& childLayer, const sp<IBinder>& relativeToHandle, int32_t relativeZ); Loading Loading @@ -791,6 +791,27 @@ private: const LayerVector::Visitor& visitor); LayerVector makeChildrenTraversalList(LayerVector::StateSet stateSet, const std::vector<Layer*>& layersInTree); /** * Retuns the child bounds in layer space cropped to its bounds as well all its parent bounds. * The cropped bounds must be transformed back from parent layer space to child layer space by * applying the inverse of the child's transformation. */ FloatRect cropChildBounds(const FloatRect& childBounds) const; /** * Returns the cropped buffer size or the layer crop if the layer has no buffer. Return * INVALID_RECT if the layer has no buffer and no crop. * A layer with an invalid buffer size and no crop is considered to be boundless. The layer * bounds are constrained by its parent bounds. */ Rect getCroppedBufferSize(const Layer::State& s) const; /** * Returns active buffer size in the correct orientation. Buffer size is determined by undoing * any buffer transformations. If the layer has no buffer then return INVALID_RECT. */ virtual Rect getBufferSize(const Layer::State&) const { return Rect::INVALID_RECT; } }; // --------------------------------------------------------------------------- Loading