summaryrefslogtreecommitdiff
path: root/libs/gui/Surface.cpp
diff options
context:
space:
mode:
author Xin Li <delphij@google.com> 2021-10-06 22:53:36 +0000
committer Xin Li <delphij@google.com> 2021-10-06 22:53:36 +0000
commit097d2a50873100486d65a69cb1cbabf37fb3b188 (patch)
treec2f19f92e4503b2de0afeebdd9bf7aeb1bb2e9c1 /libs/gui/Surface.cpp
parentcbfb18e134845deeace954bbba818acda48cb80f (diff)
parentadcb6a2733c1baf66e5ad72365965ab504f5f959 (diff)
Merge Android 12
Bug: 202323961 Merged-In: Ifb27b3eb12454fa96f07e6797745c697b4f831c4 Change-Id: I2a7f5931477fddb51564c2eabcdc96ce58888ce8
Diffstat (limited to 'libs/gui/Surface.cpp')
-rw-r--r--libs/gui/Surface.cpp451
1 files changed, 380 insertions, 71 deletions
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 8a64a4f0f7..2edb4e4ba4 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -34,9 +34,9 @@
#include <utils/NativeHandle.h>
#include <ui/DisplayStatInfo.h>
+#include <ui/DynamicDisplayInfo.h>
#include <ui/Fence.h>
#include <ui/GraphicBuffer.h>
-#include <ui/HdrCapabilities.h>
#include <ui/Region.h>
#include <gui/BufferItem.h>
@@ -48,7 +48,6 @@
namespace android {
-using ui::ColorMode;
using ui::Dataspace;
namespace {
@@ -63,13 +62,15 @@ bool isInterceptorRegistrationOp(int op) {
} // namespace
-Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp)
+Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp,
+ const sp<IBinder>& surfaceControlHandle)
: mGraphicBufferProducer(bufferProducer),
mCrop(Rect::EMPTY_RECT),
mBufferAge(0),
mGenerationNumber(0),
mSharedBufferMode(false),
mAutoRefresh(false),
+ mAutoPrerotation(false),
mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
mSharedBufferHasBeenQueued(false),
mQueriedSupportedTimestamps(false),
@@ -111,6 +112,7 @@ Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controll
mProducerControlledByApp = controlledByApp;
mSwapIntervalZero = false;
mMaxBufferCount = NUM_BUFFER_SLOTS;
+ mSurfaceControlHandle = surfaceControlHandle;
}
Surface::~Surface() {
@@ -359,15 +361,12 @@ status_t Surface::getHdrSupport(bool* supported) {
return NAME_NOT_FOUND;
}
- HdrCapabilities hdrCapabilities;
- status_t err =
- composerService()->getHdrCapabilities(display, &hdrCapabilities);
-
- if (err)
+ ui::DynamicDisplayInfo info;
+ if (status_t err = composerService()->getDynamicDisplayInfo(display, &info); err != NO_ERROR) {
return err;
+ }
- *supported = !hdrCapabilities.getSupportedHdrTypes().empty();
-
+ *supported = !info.hdrCapabilities.getSupportedHdrTypes().empty();
return NO_ERROR;
}
@@ -616,29 +615,31 @@ private:
std::mutex mMutex;
};
+void Surface::getDequeueBufferInputLocked(
+ IGraphicBufferProducer::DequeueBufferInput* dequeueInput) {
+ LOG_ALWAYS_FATAL_IF(dequeueInput == nullptr, "input is null");
+
+ dequeueInput->width = mReqWidth ? mReqWidth : mUserWidth;
+ dequeueInput->height = mReqHeight ? mReqHeight : mUserHeight;
+
+ dequeueInput->format = mReqFormat;
+ dequeueInput->usage = mReqUsage;
+
+ dequeueInput->getTimestamps = mEnableFrameTimestamps;
+}
+
int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
ATRACE_CALL();
ALOGV("Surface::dequeueBuffer");
- uint32_t reqWidth;
- uint32_t reqHeight;
- PixelFormat reqFormat;
- uint64_t reqUsage;
- bool enableFrameTimestamps;
-
+ IGraphicBufferProducer::DequeueBufferInput dqInput;
{
Mutex::Autolock lock(mMutex);
if (mReportRemovedBuffers) {
mRemovedBuffers.clear();
}
- reqWidth = mReqWidth ? mReqWidth : mUserWidth;
- reqHeight = mReqHeight ? mReqHeight : mUserHeight;
-
- reqFormat = mReqFormat;
- reqUsage = mReqUsage;
-
- enableFrameTimestamps = mEnableFrameTimestamps;
+ getDequeueBufferInputLocked(&dqInput);
if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot !=
BufferItem::INVALID_BUFFER_SLOT) {
@@ -656,16 +657,17 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
nsecs_t startTime = systemTime();
FrameEventHistoryDelta frameTimestamps;
- status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, reqWidth, reqHeight,
- reqFormat, reqUsage, &mBufferAge,
- enableFrameTimestamps ? &frameTimestamps
- : nullptr);
+ status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, dqInput.width,
+ dqInput.height, dqInput.format,
+ dqInput.usage, &mBufferAge,
+ dqInput.getTimestamps ?
+ &frameTimestamps : nullptr);
mLastDequeueDuration = systemTime() - startTime;
if (result < 0) {
ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer"
"(%d, %d, %d, %#" PRIx64 ") failed: %d",
- reqWidth, reqHeight, reqFormat, reqUsage, result);
+ dqInput.width, dqInput.height, dqInput.format, dqInput.usage, result);
return result;
}
@@ -694,7 +696,7 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
freeAllBuffers();
}
- if (enableFrameTimestamps) {
+ if (dqInput.getTimestamps) {
mFrameEventHistory->applyDelta(frameTimestamps);
}
@@ -737,6 +739,176 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
return OK;
}
+int Surface::dequeueBuffers(std::vector<BatchBuffer>* buffers) {
+ using DequeueBufferInput = IGraphicBufferProducer::DequeueBufferInput;
+ using DequeueBufferOutput = IGraphicBufferProducer::DequeueBufferOutput;
+ using CancelBufferInput = IGraphicBufferProducer::CancelBufferInput;
+ using RequestBufferOutput = IGraphicBufferProducer::RequestBufferOutput;
+
+ ATRACE_CALL();
+ ALOGV("Surface::dequeueBuffers");
+
+ if (buffers->size() == 0) {
+ ALOGE("%s: must dequeue at least 1 buffer!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ if (mSharedBufferMode) {
+ ALOGE("%s: batch operation is not supported in shared buffer mode!",
+ __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ size_t numBufferRequested = buffers->size();
+ DequeueBufferInput input;
+
+ {
+ Mutex::Autolock lock(mMutex);
+ if (mReportRemovedBuffers) {
+ mRemovedBuffers.clear();
+ }
+
+ getDequeueBufferInputLocked(&input);
+ } // Drop the lock so that we can still touch the Surface while blocking in IGBP::dequeueBuffers
+
+ std::vector<DequeueBufferInput> dequeueInput(numBufferRequested, input);
+ std::vector<DequeueBufferOutput> dequeueOutput;
+
+ nsecs_t startTime = systemTime();
+
+ status_t result = mGraphicBufferProducer->dequeueBuffers(dequeueInput, &dequeueOutput);
+
+ mLastDequeueDuration = systemTime() - startTime;
+
+ if (result < 0) {
+ ALOGV("%s: IGraphicBufferProducer::dequeueBuffers"
+ "(%d, %d, %d, %#" PRIx64 ") failed: %d",
+ __FUNCTION__, input.width, input.height, input.format, input.usage, result);
+ return result;
+ }
+
+ std::vector<CancelBufferInput> cancelBufferInputs(numBufferRequested);
+ std::vector<status_t> cancelBufferOutputs;
+ for (size_t i = 0; i < numBufferRequested; i++) {
+ cancelBufferInputs[i].slot = dequeueOutput[i].slot;
+ cancelBufferInputs[i].fence = dequeueOutput[i].fence;
+ }
+
+ for (const auto& output : dequeueOutput) {
+ if (output.result < 0) {
+ mGraphicBufferProducer->cancelBuffers(cancelBufferInputs, &cancelBufferOutputs);
+ ALOGV("%s: IGraphicBufferProducer::dequeueBuffers"
+ "(%d, %d, %d, %#" PRIx64 ") failed: %d",
+ __FUNCTION__, input.width, input.height, input.format, input.usage,
+ output.result);
+ return output.result;
+ }
+
+ if (output.slot < 0 || output.slot >= NUM_BUFFER_SLOTS) {
+ mGraphicBufferProducer->cancelBuffers(cancelBufferInputs, &cancelBufferOutputs);
+ ALOGE("%s: IGraphicBufferProducer returned invalid slot number %d",
+ __FUNCTION__, output.slot);
+ android_errorWriteLog(0x534e4554, "36991414"); // SafetyNet logging
+ return FAILED_TRANSACTION;
+ }
+
+ if (input.getTimestamps && !output.timestamps.has_value()) {
+ mGraphicBufferProducer->cancelBuffers(cancelBufferInputs, &cancelBufferOutputs);
+ ALOGE("%s: no frame timestamp returns!", __FUNCTION__);
+ return FAILED_TRANSACTION;
+ }
+
+ // this should never happen
+ ALOGE_IF(output.fence == nullptr,
+ "%s: received null Fence! slot=%d", __FUNCTION__, output.slot);
+ }
+
+ Mutex::Autolock lock(mMutex);
+
+ // Write this while holding the mutex
+ mLastDequeueStartTime = startTime;
+
+ std::vector<int32_t> requestBufferSlots;
+ requestBufferSlots.reserve(numBufferRequested);
+ // handle release all buffers and request buffers
+ for (const auto& output : dequeueOutput) {
+ if (output.result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
+ ALOGV("%s: RELEASE_ALL_BUFFERS during batch operation", __FUNCTION__);
+ freeAllBuffers();
+ break;
+ }
+ }
+
+ for (const auto& output : dequeueOutput) {
+ // Collect slots that needs requesting buffer
+ sp<GraphicBuffer>& gbuf(mSlots[output.slot].buffer);
+ if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == nullptr) {
+ if (mReportRemovedBuffers && (gbuf != nullptr)) {
+ mRemovedBuffers.push_back(gbuf);
+ }
+ requestBufferSlots.push_back(output.slot);
+ }
+ }
+
+ // Batch request Buffer
+ std::vector<RequestBufferOutput> reqBufferOutput;
+ if (requestBufferSlots.size() > 0) {
+ result = mGraphicBufferProducer->requestBuffers(requestBufferSlots, &reqBufferOutput);
+ if (result != NO_ERROR) {
+ ALOGE("%s: IGraphicBufferProducer::requestBuffers failed: %d",
+ __FUNCTION__, result);
+ mGraphicBufferProducer->cancelBuffers(cancelBufferInputs, &cancelBufferOutputs);
+ return result;
+ }
+
+ // Check if we have any single failure
+ for (size_t i = 0; i < requestBufferSlots.size(); i++) {
+ if (reqBufferOutput[i].result != OK) {
+ ALOGE("%s: IGraphicBufferProducer::requestBuffers failed at %zu-th buffer, slot %d",
+ __FUNCTION__, i, requestBufferSlots[i]);
+ mGraphicBufferProducer->cancelBuffers(cancelBufferInputs, &cancelBufferOutputs);
+ return reqBufferOutput[i].result;
+ }
+ }
+
+ // Fill request buffer results to mSlots
+ for (size_t i = 0; i < requestBufferSlots.size(); i++) {
+ mSlots[requestBufferSlots[i]].buffer = reqBufferOutput[i].buffer;
+ }
+ }
+
+ for (size_t batchIdx = 0; batchIdx < numBufferRequested; batchIdx++) {
+ const auto& output = dequeueOutput[batchIdx];
+ int slot = output.slot;
+ sp<GraphicBuffer>& gbuf(mSlots[slot].buffer);
+
+ if (CC_UNLIKELY(atrace_is_tag_enabled(ATRACE_TAG_GRAPHICS))) {
+ static FenceMonitor hwcReleaseThread("HWC release");
+ hwcReleaseThread.queueFence(output.fence);
+ }
+
+ if (input.getTimestamps) {
+ mFrameEventHistory->applyDelta(output.timestamps.value());
+ }
+
+ if (output.fence->isValid()) {
+ buffers->at(batchIdx).fenceFd = output.fence->dup();
+ if (buffers->at(batchIdx).fenceFd == -1) {
+ ALOGE("%s: error duping fence: %d", __FUNCTION__, errno);
+ // dup() should never fail; something is badly wrong. Soldier on
+ // and hope for the best; the worst that should happen is some
+ // visible corruption that lasts until the next frame.
+ }
+ } else {
+ buffers->at(batchIdx).fenceFd = -1;
+ }
+
+ buffers->at(batchIdx).buffer = gbuf.get();
+ mDequeuedSlots.insert(slot);
+ }
+ return OK;
+}
+
int Surface::cancelBuffer(android_native_buffer_t* buffer,
int fenceFd) {
ATRACE_CALL();
@@ -767,15 +939,65 @@ int Surface::cancelBuffer(android_native_buffer_t* buffer,
return OK;
}
+int Surface::cancelBuffers(const std::vector<BatchBuffer>& buffers) {
+ using CancelBufferInput = IGraphicBufferProducer::CancelBufferInput;
+ ATRACE_CALL();
+ ALOGV("Surface::cancelBuffers");
+
+ if (mSharedBufferMode) {
+ ALOGE("%s: batch operation is not supported in shared buffer mode!",
+ __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ size_t numBuffers = buffers.size();
+ std::vector<CancelBufferInput> cancelBufferInputs(numBuffers);
+ std::vector<status_t> cancelBufferOutputs;
+ size_t numBuffersCancelled = 0;
+ int badSlotResult = 0;
+ for (size_t i = 0; i < numBuffers; i++) {
+ int slot = getSlotFromBufferLocked(buffers[i].buffer);
+ int fenceFd = buffers[i].fenceFd;
+ if (slot < 0) {
+ if (fenceFd >= 0) {
+ close(fenceFd);
+ }
+ ALOGE("%s: cannot find slot number for cancelled buffer", __FUNCTION__);
+ badSlotResult = slot;
+ } else {
+ sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
+ cancelBufferInputs[numBuffersCancelled].slot = slot;
+ cancelBufferInputs[numBuffersCancelled++].fence = fence;
+ }
+ }
+ cancelBufferInputs.resize(numBuffersCancelled);
+ mGraphicBufferProducer->cancelBuffers(cancelBufferInputs, &cancelBufferOutputs);
+
+
+ for (size_t i = 0; i < numBuffersCancelled; i++) {
+ mDequeuedSlots.erase(cancelBufferInputs[i].slot);
+ }
+
+ if (badSlotResult != 0) {
+ return badSlotResult;
+ }
+ return OK;
+}
+
int Surface::getSlotFromBufferLocked(
android_native_buffer_t* buffer) const {
+ if (buffer == nullptr) {
+ ALOGE("%s: input buffer is null!", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
if (mSlots[i].buffer != nullptr &&
mSlots[i].buffer->handle == buffer->handle) {
return i;
}
}
- ALOGE("getSlotFromBufferLocked: unknown buffer: %p", buffer->handle);
+ ALOGE("%s: unknown buffer: %p", __FUNCTION__, buffer->handle);
return BAD_VALUE;
}
@@ -785,42 +1007,22 @@ int Surface::lockBuffer_DEPRECATED(android_native_buffer_t* buffer __attribute__
return OK;
}
-int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
- ATRACE_CALL();
- ALOGV("Surface::queueBuffer");
- Mutex::Autolock lock(mMutex);
- int64_t timestamp;
+void Surface::getQueueBufferInputLocked(android_native_buffer_t* buffer, int fenceFd,
+ nsecs_t timestamp, IGraphicBufferProducer::QueueBufferInput* out) {
bool isAutoTimestamp = false;
- if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
+ if (timestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
isAutoTimestamp = true;
ALOGV("Surface::queueBuffer making up timestamp: %.2f ms",
timestamp / 1000000.0);
- } else {
- timestamp = mTimestamp;
- }
- int i = getSlotFromBufferLocked(buffer);
- if (i < 0) {
- if (fenceFd >= 0) {
- close(fenceFd);
- }
- return i;
- }
- if (mSharedBufferSlot == i && mSharedBufferHasBeenQueued) {
- if (fenceFd >= 0) {
- close(fenceFd);
- }
- return OK;
}
-
// Make sure the crop rectangle is entirely inside the buffer.
Rect crop(Rect::EMPTY_RECT);
mCrop.intersect(Rect(buffer->width, buffer->height), &crop);
sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
- IGraphicBufferProducer::QueueBufferOutput output;
IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
static_cast<android_dataspace>(mDataSpace), crop, mScalingMode,
mTransform ^ mStickyTransform, fence, mStickyTransform,
@@ -891,15 +1093,12 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
input.setSurfaceDamage(flippedRegion);
}
+ *out = input;
+}
- nsecs_t now = systemTime();
- status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
- mLastQueueDuration = systemTime() - now;
- if (err != OK) {
- ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
- }
-
- mDequeuedSlots.erase(i);
+void Surface::onBufferQueuedLocked(int slot, sp<Fence> fence,
+ const IGraphicBufferProducer::QueueBufferOutput& output) {
+ mDequeuedSlots.erase(slot);
if (mEnableFrameTimestamps) {
mFrameEventHistory->applyDelta(output.frameTimestamps);
@@ -933,7 +1132,7 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
mDirtyRegion = Region::INVALID_REGION;
}
- if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot == i) {
+ if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot == slot) {
mSharedBufferHasBeenQueued = true;
}
@@ -943,6 +1142,89 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
static FenceMonitor gpuCompletionThread("GPU completion");
gpuCompletionThread.queueFence(fence);
}
+}
+
+int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
+ ATRACE_CALL();
+ ALOGV("Surface::queueBuffer");
+ Mutex::Autolock lock(mMutex);
+
+ int i = getSlotFromBufferLocked(buffer);
+ if (i < 0) {
+ if (fenceFd >= 0) {
+ close(fenceFd);
+ }
+ return i;
+ }
+ if (mSharedBufferSlot == i && mSharedBufferHasBeenQueued) {
+ if (fenceFd >= 0) {
+ close(fenceFd);
+ }
+ return OK;
+ }
+
+ IGraphicBufferProducer::QueueBufferOutput output;
+ IGraphicBufferProducer::QueueBufferInput input;
+ getQueueBufferInputLocked(buffer, fenceFd, mTimestamp, &input);
+ sp<Fence> fence = input.fence;
+
+ nsecs_t now = systemTime();
+ status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
+ mLastQueueDuration = systemTime() - now;
+ if (err != OK) {
+ ALOGE("queueBuffer: error queuing buffer, %d", err);
+ }
+
+ onBufferQueuedLocked(i, fence, output);
+ return err;
+}
+
+int Surface::queueBuffers(const std::vector<BatchQueuedBuffer>& buffers) {
+ ATRACE_CALL();
+ ALOGV("Surface::queueBuffers");
+ Mutex::Autolock lock(mMutex);
+
+ if (mSharedBufferMode) {
+ ALOGE("%s: batched operation is not supported in shared buffer mode", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ size_t numBuffers = buffers.size();
+ std::vector<IGraphicBufferProducer::QueueBufferInput> queueBufferInputs(numBuffers);
+ std::vector<IGraphicBufferProducer::QueueBufferOutput> queueBufferOutputs;
+ std::vector<int> bufferSlots(numBuffers, -1);
+ std::vector<sp<Fence>> bufferFences(numBuffers);
+
+ for (size_t batchIdx = 0; batchIdx < numBuffers; batchIdx++) {
+ int i = getSlotFromBufferLocked(buffers[batchIdx].buffer);
+ if (i < 0) {
+ if (buffers[batchIdx].fenceFd >= 0) {
+ close(buffers[batchIdx].fenceFd);
+ }
+ return i;
+ }
+ bufferSlots[batchIdx] = i;
+
+ IGraphicBufferProducer::QueueBufferInput input;
+ getQueueBufferInputLocked(
+ buffers[batchIdx].buffer, buffers[batchIdx].fenceFd, buffers[batchIdx].timestamp,
+ &input);
+ bufferFences[batchIdx] = input.fence;
+ queueBufferInputs[batchIdx] = input;
+ }
+
+ nsecs_t now = systemTime();
+ status_t err = mGraphicBufferProducer->queueBuffers(queueBufferInputs, &queueBufferOutputs);
+ mLastQueueDuration = systemTime() - now;
+ if (err != OK) {
+ ALOGE("%s: error queuing buffer, %d", __FUNCTION__, err);
+ }
+
+
+ for (size_t batchIdx = 0; batchIdx < numBuffers; batchIdx++) {
+ onBufferQueuedLocked(bufferSlots[batchIdx], bufferFences[batchIdx],
+ queueBufferOutputs[batchIdx]);
+ }
return err;
}
@@ -983,8 +1265,15 @@ int Surface::query(int what, int* value) const {
}
break;
case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
- if (composerService()->authenticateSurfaceTexture(
- mGraphicBufferProducer)) {
+ status_t err = mGraphicBufferProducer->query(what, value);
+ if (err == NO_ERROR) {
+ return NO_ERROR;
+ }
+ sp<ISurfaceComposer> surfaceComposer = composerService();
+ if (surfaceComposer == nullptr) {
+ return -EPERM; // likely permissions error
+ }
+ if (surfaceComposer->authenticateSurfaceTexture(mGraphicBufferProducer)) {
*value = 1;
} else {
*value = 0;
@@ -1003,7 +1292,7 @@ int Surface::query(int what, int* value) const {
mUserHeight ? mUserHeight : mDefaultHeight);
return NO_ERROR;
case NATIVE_WINDOW_TRANSFORM_HINT:
- *value = static_cast<int>(mTransformHint);
+ *value = static_cast<int>(getTransformHint());
return NO_ERROR;
case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: {
status_t err = NO_ERROR;
@@ -1210,6 +1499,9 @@ int Surface::perform(int operation, va_list args)
case NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER2:
res = dispatchGetLastQueuedBuffer2(args);
break;
+ case NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO:
+ res = dispatchSetFrameTimelineInfo(args);
+ break;
default:
res = NAME_NOT_FOUND;
break;
@@ -1441,7 +1733,8 @@ int Surface::dispatchGetLastQueueDuration(va_list args) {
int Surface::dispatchSetFrameRate(va_list args) {
float frameRate = static_cast<float>(va_arg(args, double));
int8_t compatibility = static_cast<int8_t>(va_arg(args, int));
- return setFrameRate(frameRate, compatibility);
+ int8_t changeFrameRateStrategy = static_cast<int8_t>(va_arg(args, int));
+ return setFrameRate(frameRate, compatibility, changeFrameRateStrategy);
}
int Surface::dispatchAddCancelInterceptor(va_list args) {
@@ -1502,7 +1795,7 @@ int Surface::dispatchGetLastQueuedBuffer(va_list args) {
int result = mGraphicBufferProducer->getLastQueuedBuffer(&graphicBuffer, &spFence, matrix);
if (graphicBuffer != nullptr) {
- *buffer = reinterpret_cast<AHardwareBuffer*>(graphicBuffer.get());
+ *buffer = graphicBuffer->toAHardwareBuffer();
AHardwareBuffer_acquire(*buffer);
} else {
*buffer = nullptr;
@@ -1549,7 +1842,16 @@ int Surface::dispatchGetLastQueuedBuffer2(va_list args) {
return result;
}
-bool Surface::transformToDisplayInverse() {
+int Surface::dispatchSetFrameTimelineInfo(va_list args) {
+ ATRACE_CALL();
+ auto frameTimelineVsyncId = static_cast<int64_t>(va_arg(args, int64_t));
+ auto inputEventId = static_cast<int32_t>(va_arg(args, int32_t));
+
+ ALOGV("Surface::%s", __func__);
+ return setFrameTimelineInfo({frameTimelineVsyncId, inputEventId});
+}
+
+bool Surface::transformToDisplayInverse() const {
return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) ==
NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
}
@@ -2302,15 +2604,22 @@ void Surface::ProducerListenerProxy::onBuffersDiscarded(const std::vector<int32_
mSurfaceListener->onBuffersDiscarded(discardedBufs);
}
-status_t Surface::setFrameRate(float frameRate, int8_t compatibility) {
+status_t Surface::setFrameRate(float frameRate, int8_t compatibility,
+ int8_t changeFrameRateStrategy) {
ATRACE_CALL();
ALOGV("Surface::setFrameRate");
- if (!ValidateFrameRate(frameRate, compatibility, "Surface::setFrameRate")) {
+ if (!ValidateFrameRate(frameRate, compatibility, changeFrameRateStrategy,
+ "Surface::setFrameRate")) {
return BAD_VALUE;
}
- return composerService()->setFrameRate(mGraphicBufferProducer, frameRate, compatibility);
+ return composerService()->setFrameRate(mGraphicBufferProducer, frameRate, compatibility,
+ changeFrameRateStrategy);
+}
+
+status_t Surface::setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) {
+ return composerService()->setFrameTimelineInfo(mGraphicBufferProducer, frameTimelineInfo);
}
}; // namespace android