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

Commit 6cdd3fd7 authored by Ady Abraham's avatar Ady Abraham
Browse files

libgui: plumb setFrameRate thru BufferQueue

The current implementation just assumes that the Surface
and BLASTBufferQueue lives in the same process and rely
on inheritance to handle setFrameRate. This doesn't work
for any usecase that the Surface is Parceled to a diffrent process.

Bug: 281695725
Test: atest CtsGraphicsTestCases --test-filter SetFrameRateTest*
Change-Id: I4e08b92b618fa7b863ca3ef4f7b46d9f1c30c775
parent 3821b0df
Loading
Loading
Loading
Loading
+32 −21
Original line number Diff line number Diff line
@@ -204,27 +204,8 @@ cc_aconfig_library {
    aconfig_declarations: "libgui_flags",
}

cc_library_shared {
    name: "libgui",
    vendor_available: true,
    vndk: {
        enabled: true,
        private: true,
    },
    double_loadable: true,

    defaults: ["libgui_bufferqueue-defaults"],

    static_libs: [
        "libgui_aidl_static",
        "libgui_window_info_static",
        "libguiflags",
    ],
    export_static_lib_headers: [
        "libgui_aidl_static",
        "libgui_window_info_static",
    ],

filegroup {
    name: "libgui-sources",
    srcs: [
        ":framework_native_aidl_binder",
        ":framework_native_aidl_gui",
@@ -268,11 +249,40 @@ cc_library_shared {
        "bufferqueue/2.0/B2HProducerListener.cpp",
        "bufferqueue/2.0/H2BGraphicBufferProducer.cpp",
    ],
}

cc_defaults {
    name: "libgui-defaults",
    defaults: ["libgui_bufferqueue-defaults"],
    srcs: [":libgui-sources"],
    static_libs: [
        "libgui_aidl_static",
        "libgui_window_info_static",
        "libguiflags",
    ],
    shared_libs: [
        "libbinder",
        "libGLESv2",
    ],
}

cc_library_shared {
    name: "libgui",
    vendor_available: true,
    vndk: {
        enabled: true,
        private: true,
    },
    double_loadable: true,

    defaults: [
        "libgui-defaults",
    ],

    export_static_lib_headers: [
        "libgui_aidl_static",
        "libgui_window_info_static",
    ],

    export_shared_lib_headers: [
        "libbinder",
@@ -346,6 +356,7 @@ filegroup {
        "BufferQueueProducer.cpp",
        "BufferQueueThreadState.cpp",
        "BufferSlot.cpp",
        "FrameRateUtils.cpp",
        "FrameTimestamps.cpp",
        "GLConsumerUtils.cpp",
        "HdrMetadata.cpp",
+19 −0
Original line number Diff line number Diff line
@@ -26,6 +26,8 @@
#include <gui/BufferQueueConsumer.h>
#include <gui/BufferQueueCore.h>
#include <gui/BufferQueueProducer.h>
#include <gui/Flags.h>
#include <gui/FrameRateUtils.h>
#include <gui/GLConsumer.h>
#include <gui/IProducerListener.h>
#include <gui/Surface.h>
@@ -39,6 +41,9 @@
#include <android-base/thread_annotations.h>
#include <chrono>

#include <com_android_graphics_libgui_flags.h>

using namespace com::android::graphics::libgui;
using namespace std::chrono_literals;

namespace {
@@ -139,6 +144,16 @@ void BLASTBufferItemConsumer::onSidebandStreamChanged() {
    }
}

#if FLAG_BQ_SET_FRAME_RATE
void BLASTBufferItemConsumer::onSetFrameRate(float frameRate, int8_t compatibility,
                                             int8_t changeFrameRateStrategy) {
    sp<BLASTBufferQueue> bbq = mBLASTBufferQueue.promote();
    if (bbq != nullptr) {
        bbq->setFrameRate(frameRate, compatibility, changeFrameRateStrategy);
    }
}
#endif

void BLASTBufferItemConsumer::resizeFrameEventHistory(size_t newSize) {
    Mutex::Autolock lock(mMutex);
    mFrameEventHistory.resize(newSize);
@@ -890,6 +905,10 @@ public:

    status_t setFrameRate(float frameRate, int8_t compatibility,
                          int8_t changeFrameRateStrategy) override {
        if (flags::bq_setframerate()) {
            return Surface::setFrameRate(frameRate, compatibility, changeFrameRateStrategy);
        }

        std::lock_guard _lock{mMutex};
        if (mDestroyed) {
            return DEAD_OBJECT;
+11 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <gui/BufferQueueConsumer.h>
#include <gui/BufferQueueCore.h>
#include <gui/BufferQueueProducer.h>
#include <gui/Flags.h>

namespace android {

@@ -98,6 +99,16 @@ void BufferQueue::ProxyConsumerListener::addAndGetFrameTimestamps(
    }
}

#if FLAG_BQ_SET_FRAME_RATE
void BufferQueue::ProxyConsumerListener::onSetFrameRate(float frameRate, int8_t compatibility,
                                                        int8_t changeFrameRateStrategy) {
    sp<ConsumerListener> listener(mConsumerListener.promote());
    if (listener != nullptr) {
        listener->onSetFrameRate(frameRate, compatibility, changeFrameRateStrategy);
    }
}
#endif

void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
        sp<IGraphicBufferConsumer>* outConsumer,
        bool consumerIsSurfaceFlinger) {
+25 −0
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@
#include <gui/BufferItem.h>
#include <gui/BufferQueueCore.h>
#include <gui/BufferQueueProducer.h>
#include <gui/Flags.h>
#include <gui/FrameRateUtils.h>
#include <gui/GLConsumer.h>
#include <gui/IConsumerListener.h>
#include <gui/IProducerListener.h>
@@ -1751,4 +1753,27 @@ status_t BufferQueueProducer::setAutoPrerotation(bool autoPrerotation) {
    return NO_ERROR;
}

#if FLAG_BQ_SET_FRAME_RATE
status_t BufferQueueProducer::setFrameRate(float frameRate, int8_t compatibility,
                                           int8_t changeFrameRateStrategy) {
    ATRACE_CALL();
    BQ_LOGV("setFrameRate: %.2f", frameRate);

    if (!ValidateFrameRate(frameRate, compatibility, changeFrameRateStrategy,
                           "BufferQueueProducer::setFrameRate")) {
        return BAD_VALUE;
    }

    sp<IConsumerListener> listener;
    {
        std::lock_guard<std::mutex> lock(mCore->mMutex);
        listener = mCore->mConsumerListener;
    }
    if (listener != nullptr) {
        listener->onSetFrameRate(frameRate, compatibility, changeFrameRateStrategy);
    }
    return NO_ERROR;
}
#endif

} // namespace android
+65 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gui/Flags.h>
#include <gui/FrameRateUtils.h>
#include <system/window.h>
#include <utils/Log.h>

#include <cmath>

namespace android {
// Returns true if the frameRate is valid.
//
// @param frameRate the frame rate in Hz
// @param compatibility a ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_*
// @param changeFrameRateStrategy a ANATIVEWINDOW_CHANGE_FRAME_RATE_*
// @param functionName calling function or nullptr. Used for logging
// @param privileged whether caller has unscoped surfaceflinger access
bool ValidateFrameRate(float frameRate, int8_t compatibility, int8_t changeFrameRateStrategy,
                       const char* inFunctionName, bool privileged) {
    const char* functionName = inFunctionName != nullptr ? inFunctionName : "call";
    int floatClassification = std::fpclassify(frameRate);
    if (frameRate < 0 || floatClassification == FP_INFINITE || floatClassification == FP_NAN) {
        ALOGE("%s failed - invalid frame rate %f", functionName, frameRate);
        return false;
    }

    if (compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT &&
        compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE &&
        (!privileged ||
         (compatibility != ANATIVEWINDOW_FRAME_RATE_EXACT &&
          compatibility != ANATIVEWINDOW_FRAME_RATE_NO_VOTE))) {
        ALOGE("%s failed - invalid compatibility value %d privileged: %s", functionName,
              compatibility, privileged ? "yes" : "no");
        return false;
    }

    if (__builtin_available(android 31, *)) {
        if (changeFrameRateStrategy != ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS &&
            changeFrameRateStrategy != ANATIVEWINDOW_CHANGE_FRAME_RATE_ALWAYS) {
            ALOGE("%s failed - invalid change frame rate strategy value %d", functionName,
                  changeFrameRateStrategy);
            if (FLAG_BQ_SET_FRAME_RATE) {
                return false;
            }
        }
    }

    return true;
}

} // namespace android
Loading