Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6b591156 authored by Vishnu Nair's avatar Vishnu Nair
Browse files

SurfaceFlinger: Add transaction proto and parser

Bug: 200284593
Test: atest libsurfaceflinger_unittest

Change-Id: Ia7cfde03a1d9df12fc6f4d35e7a93d41f680c180
parent 9666ac59
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -102,7 +102,7 @@ cc_defaults {
    // TODO (marissaw): this library is not used by surfaceflinger. This is here so
    // the library compiled in a way that is accessible to system partition when running
    // IMapper's VTS.
    required: ["libgralloctypes"]
    required: ["libgralloctypes"],
}

cc_defaults {
@@ -191,6 +191,7 @@ filegroup {
        "SurfaceFlingerDefaultFactory.cpp",
        "SurfaceInterceptor.cpp",
        "SurfaceTracing.cpp",
        "Tracing/TransactionProtoParser.cpp",
        "TransactionCallbackInvoker.cpp",
        "TunnelModeEnabledReporter.cpp",
    ],
+65 −8
Original line number Diff line number Diff line
@@ -53,26 +53,50 @@ void LayerProtoHelper::writeToProto(const Region& region,
        return;
    }

    writeToProto(region, getRegionProto());
}

void LayerProtoHelper::writeToProto(const Region& region, RegionProto* regionProto) {
    if (region.isEmpty()) {
        return;
    }

    Region::const_iterator head = region.begin();
    Region::const_iterator const tail = region.end();
    // Use a lambda do avoid writing the object header when the object is empty
    RegionProto* regionProto = getRegionProto();
    while (head != tail) {
        std::function<RectProto*()> getProtoRect = [&]() { return regionProto->add_rect(); };
        writeToProto(*head, getProtoRect);
        writeToProto(*head, regionProto->add_rect());
        head++;
    }
}

void LayerProtoHelper::readFromProto(const RegionProto& regionProto, Region& outRegion) {
    for (int i = 0; i < regionProto.rect_size(); i++) {
        Rect rect;
        readFromProto(regionProto.rect(i), rect);
        outRegion.orSelf(rect);
    }
}

void LayerProtoHelper::writeToProto(const Rect& rect, std::function<RectProto*()> getRectProto) {
    if (rect.left != 0 || rect.right != 0 || rect.top != 0 || rect.bottom != 0) {
        // Use a lambda do avoid writing the object header when the object is empty
        RectProto* rectProto = getRectProto();
        writeToProto(rect, getRectProto());
    }
}

void LayerProtoHelper::writeToProto(const Rect& rect, RectProto* rectProto) {
    rectProto->set_left(rect.left);
    rectProto->set_top(rect.top);
    rectProto->set_bottom(rect.bottom);
    rectProto->set_right(rect.right);
}

void LayerProtoHelper::readFromProto(const RectProto& proto, Rect& outRect) {
    outRect.left = proto.left();
    outRect.top = proto.top();
    outRect.bottom = proto.bottom();
    outRect.right = proto.right();
}

void LayerProtoHelper::writeToProto(const FloatRect& rect,
@@ -189,6 +213,39 @@ void LayerProtoHelper::writeToProto(const mat4 matrix, ColorTransformProto* colo
    }
}

void LayerProtoHelper::readFromProto(const ColorTransformProto& colorTransformProto, mat4& matrix) {
    for (int i = 0; i < mat4::ROW_SIZE; i++) {
        for (int j = 0; j < mat4::COL_SIZE; j++) {
            matrix[i][j] = colorTransformProto.val(i * mat4::COL_SIZE + j);
        }
    }
}

void LayerProtoHelper::writeToProto(const android::BlurRegion region, BlurRegion* proto) {
    proto->set_blur_radius(region.blurRadius);
    proto->set_corner_radius_tl(region.cornerRadiusTL);
    proto->set_corner_radius_tr(region.cornerRadiusTR);
    proto->set_corner_radius_bl(region.cornerRadiusBL);
    proto->set_corner_radius_br(region.cornerRadiusBR);
    proto->set_alpha(region.alpha);
    proto->set_left(region.left);
    proto->set_top(region.top);
    proto->set_right(region.right);
    proto->set_bottom(region.bottom);
}

void LayerProtoHelper::readFromProto(const BlurRegion& proto, android::BlurRegion& outRegion) {
    outRegion.blurRadius = proto.blur_radius();
    outRegion.cornerRadiusTL = proto.corner_radius_tl();
    outRegion.cornerRadiusTR = proto.corner_radius_tr();
    outRegion.cornerRadiusBL = proto.corner_radius_bl();
    outRegion.cornerRadiusBR = proto.corner_radius_br();
    outRegion.alpha = proto.alpha();
    outRegion.left = proto.left();
    outRegion.top = proto.top();
    outRegion.right = proto.right();
    outRegion.bottom = proto.bottom();
}
} // namespace surfaceflinger
} // namespace android

+8 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <Layer.h>
#include <gui/WindowInfo.h>
#include <math/vec4.h>
#include <ui/BlurRegion.h>
#include <ui/GraphicBuffer.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -33,9 +34,13 @@ public:
    static void writeSizeToProto(const uint32_t w, const uint32_t h,
                                 std::function<SizeProto*()> getSizeProto);
    static void writeToProto(const Rect& rect, std::function<RectProto*()> getRectProto);
    static void writeToProto(const Rect& rect, RectProto* rectProto);
    static void readFromProto(const RectProto& proto, Rect& outRect);
    static void writeToProto(const FloatRect& rect,
                             std::function<FloatRectProto*()> getFloatRectProto);
    static void writeToProto(const Region& region, std::function<RegionProto*()> getRegionProto);
    static void writeToProto(const Region& region, RegionProto* regionProto);
    static void readFromProto(const RegionProto& regionProto, Region& outRegion);
    static void writeToProto(const half4 color, std::function<ColorProto*()> getColorProto);
    // This writeToProto for transform is incorrect, but due to backwards compatibility, we can't
    // update Layers to use it. Use writeTransformToProto for any new transform proto data.
@@ -49,6 +54,9 @@ public:
                             const wp<Layer>& touchableRegionBounds,
                             std::function<InputWindowInfoProto*()> getInputWindowInfoProto);
    static void writeToProto(const mat4 matrix, ColorTransformProto* colorTransformProto);
    static void readFromProto(const ColorTransformProto& colorTransformProto, mat4& matrix);
    static void writeToProto(const android::BlurRegion region, BlurRegion*);
    static void readFromProto(const BlurRegion& proto, android::BlurRegion& outRegion);
};

} // namespace surfaceflinger
+1 −1
Original line number Diff line number Diff line
@@ -6789,7 +6789,7 @@ int SurfaceFlinger::getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) con
    return calculateMaxAcquiredBufferCount(refreshRate, presentLatency);
}

void SurfaceFlinger::TransactionState::traverseStatesWithBuffers(
void TransactionState::traverseStatesWithBuffers(
        std::function<void(const layer_state_t&)> visitor) {
    for (const auto& state : states) {
        if (state.state.hasBufferChanges() && state.state.hasValidBuffer() && state.state.surface) {
+1 −90
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@
#include "SurfaceTracing.h"
#include "TracedOrdinal.h"
#include "TransactionCallbackInvoker.h"
#include "TransactionState.h"

#include <atomic>
#include <cstdint>
@@ -461,96 +462,6 @@ private:
        hal::Connection connection = hal::Connection::INVALID;
    };

    class CountDownLatch {
    public:
        enum {
            eSyncTransaction = 1 << 0,
            eSyncInputWindows = 1 << 1,
        };
        explicit CountDownLatch(uint32_t flags) : mFlags(flags) {}

        // True if there is no waiting condition after count down.
        bool countDown(uint32_t flag) {
            std::unique_lock<std::mutex> lock(mMutex);
            if (mFlags == 0) {
                return true;
            }
            mFlags &= ~flag;
            if (mFlags == 0) {
                mCountDownComplete.notify_all();
                return true;
            }
            return false;
        }

        // Return true if triggered.
        bool wait_until(const std::chrono::seconds& timeout) const {
            std::unique_lock<std::mutex> lock(mMutex);
            const auto untilTime = std::chrono::system_clock::now() + timeout;
            while (mFlags != 0) {
                // Conditional variables can be woken up sporadically, so we check count
                // to verify the wakeup was triggered by |countDown|.
                if (std::cv_status::timeout == mCountDownComplete.wait_until(lock, untilTime)) {
                    return false;
                }
            }
            return true;
        }

    private:
        uint32_t mFlags;
        mutable std::condition_variable mCountDownComplete;
        mutable std::mutex mMutex;
    };

    struct TransactionState {
        TransactionState(const FrameTimelineInfo& frameTimelineInfo,
                         const Vector<ComposerState>& composerStates,
                         const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
                         const sp<IBinder>& applyToken,
                         const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
                         bool isAutoTimestamp, const client_cache_t& uncacheBuffer,
                         int64_t postTime, uint32_t permissions, bool hasListenerCallbacks,
                         std::vector<ListenerCallbacks> listenerCallbacks, int originPid,
                         int originUid, uint64_t transactionId)
              : frameTimelineInfo(frameTimelineInfo),
                states(composerStates),
                displays(displayStates),
                flags(transactionFlags),
                applyToken(applyToken),
                inputWindowCommands(inputWindowCommands),
                desiredPresentTime(desiredPresentTime),
                isAutoTimestamp(isAutoTimestamp),
                buffer(uncacheBuffer),
                postTime(postTime),
                permissions(permissions),
                hasListenerCallbacks(hasListenerCallbacks),
                listenerCallbacks(listenerCallbacks),
                originPid(originPid),
                originUid(originUid),
                id(transactionId) {}

        void traverseStatesWithBuffers(std::function<void(const layer_state_t&)> visitor);

        FrameTimelineInfo frameTimelineInfo;
        Vector<ComposerState> states;
        Vector<DisplayState> displays;
        uint32_t flags;
        sp<IBinder> applyToken;
        InputWindowCommands inputWindowCommands;
        const int64_t desiredPresentTime;
        const bool isAutoTimestamp;
        client_cache_t buffer;
        const int64_t postTime;
        uint32_t permissions;
        bool hasListenerCallbacks;
        std::vector<ListenerCallbacks> listenerCallbacks;
        int originPid;
        int originUid;
        uint64_t id;
        std::shared_ptr<CountDownLatch> transactionCommittedSignal;
    };

    template <typename F, std::enable_if_t<!std::is_member_function_pointer_v<F>>* = nullptr>
    static Dumper dumper(F&& dump) {
        using namespace std::placeholders;
Loading