forked from PeterGSI/patches
297 lines
10 KiB
Diff
297 lines
10 KiB
Diff
From 8dd1136bfd5a9dc403dc24839de2cbd1fe5cd273 Mon Sep 17 00:00:00 2001
|
|
From: Pierre-Hugues Husson <phh@phh.me>
|
|
Date: Sat, 25 Nov 2023 08:15:28 -0500
|
|
Subject: [PATCH 2/3] Add MTK GED KPI support to fix broken Mediatek gpufreq
|
|
|
|
Mediatek GPU scheduler likes to have the timestamps of the frames to be
|
|
able to adjust DVFS.
|
|
Technically this isn't completely needed, because it looks like DVFS can
|
|
work once we started triggering /proc/ged. But now that the work is
|
|
done, let's do it completely.
|
|
|
|
In benchmarks on Poco X4 GT, before this patch result is 1500, after is
|
|
5700. If we disable the patch after enabling it without rebooting, it
|
|
goes to 5400. So looks like GED KPI thingy does try to do a bit more
|
|
than just standard DVFS.
|
|
|
|
Thanks @sarthakroy2002 for the help and support (other people helped as
|
|
well)
|
|
|
|
Change-Id: Ic29a231ea8651efd598083611197aaa9e3c1fbbe
|
|
---
|
|
libs/gui/Surface.cpp | 202 +++++++++++++++++++++++++++++++++
|
|
libs/gui/include/gui/Surface.h | 3 +
|
|
2 files changed, 205 insertions(+)
|
|
|
|
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
|
|
index 66e7ddd..32070fa 100644
|
|
--- a/libs/gui/Surface.cpp
|
|
+++ b/libs/gui/Surface.cpp
|
|
@@ -26,6 +26,9 @@
|
|
#include <deque>
|
|
#include <mutex>
|
|
#include <thread>
|
|
+#include <sys/ioctl.h>
|
|
+#include <fcntl.h>
|
|
+#include <unistd.h>
|
|
|
|
#include <inttypes.h>
|
|
|
|
@@ -50,6 +53,9 @@
|
|
#include <gui/LayerState.h>
|
|
#include <private/gui/ComposerService.h>
|
|
#include <private/gui/ComposerServiceAIDL.h>
|
|
+#include <android-base/properties.h>
|
|
+
|
|
+#include <binder/IPCThreadState.h>
|
|
|
|
#include <com_android_graphics_libgui_flags.h>
|
|
|
|
@@ -76,6 +82,37 @@ bool isInterceptorRegistrationOp(int op) {
|
|
}
|
|
|
|
} // namespace
|
|
+ //
|
|
+#define GED_MAGIC 'g'
|
|
+#define GED_BRIDGE_COMMAND_GPU_TIMESTAMP 103
|
|
+#define GED_IOWR(INDEX) _IOWR(GED_MAGIC, INDEX, GED_BRIDGE_PACKAGE)
|
|
+#define GED_BRIDGE_IO_GPU_TIMESTAMP \
|
|
+ GED_IOWR(GED_BRIDGE_COMMAND_GPU_TIMESTAMP)
|
|
+typedef struct _GED_BRIDGE_PACKAGE {
|
|
+ unsigned int ui32FunctionID;
|
|
+ int i32Size;
|
|
+ void *pvParamIn;
|
|
+ int i32InBufferSize;
|
|
+ void *pvParamOut;
|
|
+ int i32OutBufferSize;
|
|
+} GED_BRIDGE_PACKAGE;
|
|
+
|
|
+struct GED_BRIDGE_IN_GPU_TIMESTAMP {
|
|
+ int pid;
|
|
+ uint64_t ullWnd;
|
|
+ int32_t i32FrameID;
|
|
+ int fence_fd;
|
|
+ int QedBuffer_length;
|
|
+ int isSF;
|
|
+};
|
|
+
|
|
+struct GED_BRIDGE_OUT_GPU_TIMESTAMP {
|
|
+ int eError;
|
|
+ int is_ged_kpi_enabled;
|
|
+};
|
|
+
|
|
+static int doMtkGedKpi = -1;
|
|
+static int ged_fd = -1;
|
|
|
|
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
|
|
Surface::ProducerDeathListenerProxy::ProducerDeathListenerProxy(wp<SurfaceListener> surfaceListener)
|
|
@@ -147,6 +184,47 @@ Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controll
|
|
mSwapIntervalZero = false;
|
|
mMaxBufferCount = NUM_BUFFER_SLOTS;
|
|
mSurfaceControlHandle = surfaceControlHandle;
|
|
+
|
|
+ if (doMtkGedKpi == -1) {
|
|
+ doMtkGedKpi = android::base::GetIntProperty("persist.sys.phh.mtk_ged_kpi", 0);
|
|
+ }
|
|
+
|
|
+ if (ged_fd == -1 && doMtkGedKpi == 1) {
|
|
+ ALOGE("Opening ged");
|
|
+ ged_fd = open("/proc/ged", O_RDONLY);
|
|
+ ALOGE("Opening ged ret = %d", ged_fd);
|
|
+ {
|
|
+ struct GED_BRIDGE_IN_GPU_TIMESTAMP in = {
|
|
+ .pid = 0,
|
|
+ //.ullWnd = (uint64_t)(intptr_t)this,
|
|
+ .ullWnd = 0,
|
|
+ .i32FrameID = 0,
|
|
+ .fence_fd = 0,
|
|
+ .isSF = 0,
|
|
+ .QedBuffer_length = 0,
|
|
+ };
|
|
+ struct GED_BRIDGE_OUT_GPU_TIMESTAMP out;
|
|
+ memset(&in, 0, sizeof(in));
|
|
+ GED_BRIDGE_PACKAGE package = {
|
|
+ .ui32FunctionID = GED_BRIDGE_IO_GPU_TIMESTAMP,
|
|
+ .i32Size = sizeof(GED_BRIDGE_PACKAGE),
|
|
+ .pvParamIn = &in,
|
|
+ .i32InBufferSize = sizeof(in),
|
|
+ .pvParamOut = &out,
|
|
+ .i32OutBufferSize = sizeof(out),
|
|
+ };
|
|
+ if (ged_fd >= 0) {
|
|
+ int ret = ioctl(ged_fd, GED_BRIDGE_IO_GPU_TIMESTAMP, &package);
|
|
+ ALOGE("First null timestamp ioctl returned %d %d %d", ret, out.eError, out.is_ged_kpi_enabled);
|
|
+ if (out.is_ged_kpi_enabled != 1) {
|
|
+ ALOGE("is_ged_kpi_enabled reported disabled");
|
|
+ doMtkGedKpi = 0;
|
|
+ }
|
|
+ } else {
|
|
+ ALOGE("No /proc/ged");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
Surface::~Surface() {
|
|
@@ -699,6 +777,36 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
|
|
}
|
|
}
|
|
|
|
+ if (mGraphicBufferProducer != nullptr && ged_fd >= 0) {
|
|
+ uint64_t uniqueId;
|
|
+ mGraphicBufferProducer->getUniqueId(&uniqueId);
|
|
+
|
|
+ const int32_t dupFenceFd = fence->isValid() ? fence->dup() : -1;
|
|
+
|
|
+ struct GED_BRIDGE_IN_GPU_TIMESTAMP in = {
|
|
+ .pid = mPid,
|
|
+ .ullWnd = uniqueId,
|
|
+ .i32FrameID = static_cast<int32_t>(reinterpret_cast<intptr_t>(gbuf->handle)) & 0x3fffffff,
|
|
+ .fence_fd = dupFenceFd,
|
|
+ .isSF = mIsSurfaceFlinger ? 1 : 0,
|
|
+ .QedBuffer_length = -2,
|
|
+ };
|
|
+ struct GED_BRIDGE_OUT_GPU_TIMESTAMP out;
|
|
+ memset(&out, 0, sizeof(out));
|
|
+ GED_BRIDGE_PACKAGE package = {
|
|
+ .ui32FunctionID = GED_BRIDGE_IO_GPU_TIMESTAMP,
|
|
+ .i32Size = sizeof(GED_BRIDGE_PACKAGE),
|
|
+ .pvParamIn = &in,
|
|
+ .i32InBufferSize = sizeof(in),
|
|
+ .pvParamOut = &out,
|
|
+ .i32OutBufferSize = sizeof(out),
|
|
+ };
|
|
+
|
|
+ int ret = ioctl(ged_fd, GED_BRIDGE_IO_GPU_TIMESTAMP, &package);
|
|
+ ALOGV("GPU timestamp ioctl returned %d %d %d %d", ret, out.eError, out.is_ged_kpi_enabled, in.i32FrameID);
|
|
+
|
|
+ close(dupFenceFd);
|
|
+ }
|
|
if (fence->isValid()) {
|
|
*fenceFd = fence->dup();
|
|
if (*fenceFd == -1) {
|
|
@@ -1187,6 +1295,60 @@ void Surface::onBufferQueuedLocked(int slot, sp<Fence> fence,
|
|
}
|
|
|
|
mQueueBufferCondition.broadcast();
|
|
+ if (mGraphicBufferProducer != nullptr && ged_fd >= 0) {
|
|
+ sp<GraphicBuffer>& gbuf(mSlots[slot].buffer);
|
|
+ uint64_t uniqueId;
|
|
+ mGraphicBufferProducer->getUniqueId(&uniqueId);
|
|
+
|
|
+ const int32_t dupFenceFd = fence->isValid() ? fence->dup() : -1;
|
|
+ // onQueue
|
|
+ {
|
|
+ struct GED_BRIDGE_IN_GPU_TIMESTAMP in = {
|
|
+ .pid = mPid,
|
|
+ .ullWnd = uniqueId,
|
|
+ .i32FrameID = static_cast<int32_t>(reinterpret_cast<intptr_t>(gbuf->handle)) & 0x3fffffff,
|
|
+ .fence_fd = dupFenceFd,
|
|
+ .isSF = mIsSurfaceFlinger ? 1 : 0,
|
|
+ .QedBuffer_length = static_cast<int>(output.numPendingBuffers),
|
|
+ };
|
|
+ struct GED_BRIDGE_OUT_GPU_TIMESTAMP out;
|
|
+ memset(&out, 0, sizeof(out));
|
|
+ GED_BRIDGE_PACKAGE package = {
|
|
+ .ui32FunctionID = GED_BRIDGE_IO_GPU_TIMESTAMP,
|
|
+ .i32Size = sizeof(GED_BRIDGE_PACKAGE),
|
|
+ .pvParamIn = &in,
|
|
+ .i32InBufferSize = sizeof(in),
|
|
+ .pvParamOut = &out,
|
|
+ .i32OutBufferSize = sizeof(out),
|
|
+ };
|
|
+ int ret = ioctl(ged_fd, GED_BRIDGE_IO_GPU_TIMESTAMP, &package);
|
|
+ ALOGV("GPU timestamp ioctl returned %d %d %d", ret, out.eError, in.i32FrameID);
|
|
+ }
|
|
+ // acquire
|
|
+ {
|
|
+ struct GED_BRIDGE_IN_GPU_TIMESTAMP in = {
|
|
+ .pid = mPid,
|
|
+ .isSF = mIsSurfaceFlinger ? 1 : 0,
|
|
+ .ullWnd = uniqueId,
|
|
+ .i32FrameID = static_cast<int32_t>(reinterpret_cast<intptr_t>(gbuf->handle)) & 0x3fffffff,
|
|
+ .fence_fd = dupFenceFd,
|
|
+ .QedBuffer_length = -1,
|
|
+ };
|
|
+ struct GED_BRIDGE_OUT_GPU_TIMESTAMP out;
|
|
+ memset(&out, 0, sizeof(out));
|
|
+ GED_BRIDGE_PACKAGE package = {
|
|
+ .ui32FunctionID = GED_BRIDGE_IO_GPU_TIMESTAMP,
|
|
+ .i32Size = sizeof(GED_BRIDGE_PACKAGE),
|
|
+ .pvParamIn = &in,
|
|
+ .i32InBufferSize = sizeof(in),
|
|
+ .pvParamOut = &in,
|
|
+ .i32OutBufferSize = sizeof(out),
|
|
+ };
|
|
+ int ret = ioctl(ged_fd, GED_BRIDGE_IO_GPU_TIMESTAMP, &package);
|
|
+ ALOGV("GPU timestamp ioctl returned %d %d %d", ret, out.eError, in.i32FrameID);
|
|
+ }
|
|
+ close(dupFenceFd);
|
|
+ }
|
|
|
|
if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) {
|
|
static gui::FenceMonitor gpuCompletionThread("GPU completion");
|
|
@@ -2111,6 +2273,46 @@ int Surface::connect(int api, const sp<SurfaceListener>& listener, bool reportBu
|
|
}
|
|
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
|
|
}
|
|
+
|
|
+ // For MTK GED KPI, we need to grab the Surface owner's PID
|
|
+ // and also know whether that owner is surfaceflinger
|
|
+ if (api == NATIVE_WINDOW_API_EGL && ged_fd >= 0) {
|
|
+ IPCThreadState *ipc = IPCThreadState::selfOrNull();
|
|
+ const sp<IBinder>& token = IInterface::asBinder(mGraphicBufferProducer);
|
|
+ mPid = (token != NULL && NULL != token->localBinder())
|
|
+ ? getpid()
|
|
+ : (ipc != nullptr)?ipc->getCallingPid():-1;
|
|
+
|
|
+ // We've got caller PID. Now checking whether it is surfaceflinger
|
|
+ char cmdline[128];
|
|
+ char path[128];
|
|
+ snprintf(path, sizeof(path)-1, "/proc/%d/cmdline", mPid);
|
|
+ int fd = open(path, O_RDONLY);
|
|
+ read(fd, cmdline, sizeof(cmdline)-1);
|
|
+ // Normally cmdline is already \0-separated, but well
|
|
+ for(unsigned i=0; i<sizeof(cmdline); i++)
|
|
+ if(cmdline[i] == '\n')
|
|
+ cmdline[i] = 0;
|
|
+ cmdline[sizeof(cmdline)-1] = 0;
|
|
+
|
|
+ close(fd);
|
|
+
|
|
+ // Truncate to last / (also called basename)
|
|
+ const char *c = strrchr(cmdline, '/');
|
|
+ if (c != nullptr) {
|
|
+ c = c+1;
|
|
+ } else {
|
|
+ c = cmdline;
|
|
+ }
|
|
+ if(strcmp(c, "surfaceflinger") == 0) {
|
|
+ ALOGE("is surfaceflinger = 1");
|
|
+ mIsSurfaceFlinger = true;
|
|
+ } else {
|
|
+ ALOGE("is surfaceflinger = 0");
|
|
+ mIsSurfaceFlinger = false;
|
|
+ }
|
|
+ }
|
|
+
|
|
if (!err && api == NATIVE_WINDOW_API_CPU) {
|
|
mConnectedToCpu = true;
|
|
// Clear the dirty region in case we're switching from a non-CPU API
|
|
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
|
|
index 14a3513..e0843a8 100644
|
|
--- a/libs/gui/include/gui/Surface.h
|
|
+++ b/libs/gui/include/gui/Surface.h
|
|
@@ -742,6 +742,9 @@ protected:
|
|
|
|
// Buffers that are successfully dequeued/attached and handed to clients
|
|
std::unordered_set<int> mDequeuedSlots;
|
|
+
|
|
+ pid_t mPid;
|
|
+ bool mIsSurfaceFlinger;
|
|
};
|
|
|
|
} // namespace android
|
|
--
|
|
2.44.0
|
|
|