blob: 9b1330fc048a951ba4413962e23094899a20d463 [file] [log] [blame]
/*
* Copyright 2018 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 <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <android/native_window.h>
#include <android/surface_control.h>
#include <android/surface_control_jni.h>
#include <android_runtime/android_view_SurfaceControl.h>
#include <configstore/Utils.h>
#include <gui/HdrMetadata.h>
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/SurfaceControl.h>
#include <private/android/choreographer.h>
#include <surface_control_private.h>
#include <ui/DynamicDisplayInfo.h>
#include <utils/Timers.h>
#include <utility>
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
using namespace android;
using Transaction = SurfaceComposerClient::Transaction;
#define CHECK_NOT_NULL(name) \
LOG_ALWAYS_FATAL_IF(name == nullptr, "nullptr passed as " #name " argument");
#define CHECK_VALID_RECT(name) \
LOG_ALWAYS_FATAL_IF(!static_cast<const Rect&>(name).isValid(), \
"invalid arg passed as " #name " argument");
static_assert(static_cast<int>(ADATASPACE_UNKNOWN) == static_cast<int>(HAL_DATASPACE_UNKNOWN));
static_assert(static_cast<int>(ADATASPACE_SCRGB_LINEAR) ==
static_cast<int>(HAL_DATASPACE_V0_SCRGB_LINEAR));
static_assert(static_cast<int>(ADATASPACE_SRGB) == static_cast<int>(HAL_DATASPACE_V0_SRGB));
static_assert(static_cast<int>(ADATASPACE_SCRGB) == static_cast<int>(HAL_DATASPACE_V0_SCRGB));
static_assert(static_cast<int>(ADATASPACE_DISPLAY_P3) ==
static_cast<int>(HAL_DATASPACE_DISPLAY_P3));
static_assert(static_cast<int>(ADATASPACE_BT2020_PQ) == static_cast<int>(HAL_DATASPACE_BT2020_PQ));
Transaction* ASurfaceTransaction_to_Transaction(ASurfaceTransaction* aSurfaceTransaction) {
return reinterpret_cast<Transaction*>(aSurfaceTransaction);
}
SurfaceControl* ASurfaceControl_to_SurfaceControl(ASurfaceControl* aSurfaceControl) {
return reinterpret_cast<SurfaceControl*>(aSurfaceControl);
}
void SurfaceControl_acquire(SurfaceControl* surfaceControl) {
// incStrong/decStrong token must be the same, doesn't matter what it is
surfaceControl->incStrong((void*)SurfaceControl_acquire);
}
void SurfaceControl_release(SurfaceControl* surfaceControl) {
// incStrong/decStrong token must be the same, doesn't matter what it is
surfaceControl->decStrong((void*)SurfaceControl_acquire);
}
ASurfaceControl* ASurfaceControl_createFromWindow(ANativeWindow* window, const char* debug_name) {
CHECK_NOT_NULL(window);
CHECK_NOT_NULL(debug_name);
sp<SurfaceComposerClient> client = new SurfaceComposerClient();
if (client->initCheck() != NO_ERROR) {
return nullptr;
}
Surface* surface = static_cast<Surface*>(window);
sp<IBinder> parentHandle = surface->getSurfaceControlHandle();
int32_t flags = ISurfaceComposerClient::eFXSurfaceBufferState;
sp<SurfaceControl> surfaceControl;
if (parentHandle) {
surfaceControl =
client->createSurface(String8(debug_name), 0 /* width */, 0 /* height */,
// Format is only relevant for buffer queue layers.
PIXEL_FORMAT_UNKNOWN /* format */, flags, parentHandle);
} else {
// deprecated, this should no longer be used
surfaceControl = nullptr;
}
if (!surfaceControl) {
return nullptr;
}
SurfaceControl_acquire(surfaceControl.get());
return reinterpret_cast<ASurfaceControl*>(surfaceControl.get());
}
ASurfaceControl* ASurfaceControl_create(ASurfaceControl* parent, const char* debug_name) {
CHECK_NOT_NULL(parent);
CHECK_NOT_NULL(debug_name);
SurfaceComposerClient* client = ASurfaceControl_to_SurfaceControl(parent)->getClient().get();
SurfaceControl* surfaceControlParent = ASurfaceControl_to_SurfaceControl(parent);
uint32_t flags = ISurfaceComposerClient::eFXSurfaceBufferState;
sp<SurfaceControl> surfaceControl =
client->createSurface(String8(debug_name), 0 /* width */, 0 /* height */,
// Format is only relevant for buffer queue layers.
PIXEL_FORMAT_UNKNOWN /* format */, flags,
surfaceControlParent->getHandle());
if (!surfaceControl) {
return nullptr;
}
SurfaceControl_acquire(surfaceControl.get());
return reinterpret_cast<ASurfaceControl*>(surfaceControl.get());
}
void ASurfaceControl_acquire(ASurfaceControl* aSurfaceControl) {
SurfaceControl* surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
SurfaceControl_acquire(surfaceControl);
}
void ASurfaceControl_release(ASurfaceControl* aSurfaceControl) {
SurfaceControl* surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
SurfaceControl_release(surfaceControl);
}
ASurfaceControl* ASurfaceControl_fromJava(JNIEnv* env, jobject surfaceControlObj) {
LOG_ALWAYS_FATAL_IF(!env, "nullptr passed to ASurfaceControl_fromJava as env argument");
LOG_ALWAYS_FATAL_IF(!surfaceControlObj,
"nullptr passed to ASurfaceControl_fromJava as surfaceControlObj argument");
SurfaceControl* surfaceControl =
android_view_SurfaceControl_getNativeSurfaceControl(env, surfaceControlObj);
LOG_ALWAYS_FATAL_IF(!surfaceControl,
"surfaceControlObj passed to ASurfaceControl_fromJava is not valid");
SurfaceControl_acquire(surfaceControl);
return reinterpret_cast<ASurfaceControl*>(surfaceControl);
}
struct ASurfaceControlStats {
std::variant<int64_t, sp<Fence>> acquireTimeOrFence;
sp<Fence> previousReleaseFence;
uint64_t frameNumber;
};
void ASurfaceControl_registerSurfaceStatsListener(ASurfaceControl* control, int32_t id,
void* context,
ASurfaceControl_SurfaceStatsListener func) {
SurfaceStatsCallback callback = [func, id](void* callback_context, nsecs_t, const sp<Fence>&,
const SurfaceStats& surfaceStats) {
ASurfaceControlStats aSurfaceControlStats;
aSurfaceControlStats.acquireTimeOrFence = surfaceStats.acquireTimeOrFence;
aSurfaceControlStats.previousReleaseFence = surfaceStats.previousReleaseFence;
aSurfaceControlStats.frameNumber = surfaceStats.eventStats.frameNumber;
(*func)(callback_context, id, &aSurfaceControlStats);
};
TransactionCompletedListener::getInstance()->addSurfaceStatsListener(context,
reinterpret_cast<void*>(func), ASurfaceControl_to_SurfaceControl(control), callback);
}
void ASurfaceControl_unregisterSurfaceStatsListener(void* context,
ASurfaceControl_SurfaceStatsListener func) {
TransactionCompletedListener::getInstance()->removeSurfaceStatsListener(context,
reinterpret_cast<void*>(func));
}
AChoreographer* ASurfaceControl_getChoreographer(ASurfaceControl* aSurfaceControl) {
LOG_ALWAYS_FATAL_IF(aSurfaceControl == nullptr, "aSurfaceControl should not be nullptr");
SurfaceControl* surfaceControl =
ASurfaceControl_to_SurfaceControl(reinterpret_cast<ASurfaceControl*>(aSurfaceControl));
if (!surfaceControl->isValid()) {
ALOGE("Attempted to get choreographer from invalid surface control");
return nullptr;
}
SurfaceControl_acquire(surfaceControl);
return reinterpret_cast<AChoreographer*>(surfaceControl->getChoreographer().get());
}
int64_t ASurfaceControlStats_getAcquireTime(ASurfaceControlStats* stats) {
if (const auto* fence = std::get_if<sp<Fence>>(&stats->acquireTimeOrFence)) {
// We got a fence instead of the acquire time due to latch unsignaled.
// Ideally the client could just get the acquire time dericly from
// the fence instead of calling this function which needs to block.
(*fence)->waitForever("ASurfaceControlStats_getAcquireTime");
return (*fence)->getSignalTime();
}
return std::get<int64_t>(stats->acquireTimeOrFence);
}
uint64_t ASurfaceControlStats_getFrameNumber(ASurfaceControlStats* stats) {
return stats->frameNumber;
}
ASurfaceTransaction* ASurfaceTransaction_create() {
Transaction* transaction = new Transaction;
return reinterpret_cast<ASurfaceTransaction*>(transaction);
}
void ASurfaceTransaction_delete(ASurfaceTransaction* aSurfaceTransaction) {
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
delete transaction;
}
ASurfaceTransaction* ASurfaceTransaction_fromJava(JNIEnv* env, jobject transactionObj) {
LOG_ALWAYS_FATAL_IF(!env, "nullptr passed to ASurfaceTransaction_fromJava as env argument");
LOG_ALWAYS_FATAL_IF(!transactionObj,
"nullptr passed to ASurfaceTransaction_fromJava as transactionObj "
"argument");
Transaction* transaction =
android_view_SurfaceTransaction_getNativeSurfaceTransaction(env, transactionObj);
LOG_ALWAYS_FATAL_IF(!transaction,
"surfaceControlObj passed to ASurfaceTransaction_fromJava is not valid");
return reinterpret_cast<ASurfaceTransaction*>(transaction);
}
void ASurfaceTransaction_apply(ASurfaceTransaction* aSurfaceTransaction) {
CHECK_NOT_NULL(aSurfaceTransaction);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
transaction->apply();
}
struct ASurfaceTransactionStats {
std::unordered_map<ASurfaceControl*, ASurfaceControlStats> aSurfaceControlStats;
int64_t latchTime;
sp<Fence> presentFence;
bool transactionCompleted;
};
int64_t ASurfaceTransactionStats_getLatchTime(ASurfaceTransactionStats* aSurfaceTransactionStats) {
CHECK_NOT_NULL(aSurfaceTransactionStats);
return aSurfaceTransactionStats->latchTime;
}
int ASurfaceTransactionStats_getPresentFenceFd(ASurfaceTransactionStats* aSurfaceTransactionStats) {
CHECK_NOT_NULL(aSurfaceTransactionStats);
LOG_ALWAYS_FATAL_IF(!aSurfaceTransactionStats->transactionCompleted,
"ASurfaceTransactionStats queried from an incomplete transaction callback");
auto& presentFence = aSurfaceTransactionStats->presentFence;
return (presentFence) ? presentFence->dup() : -1;
}
void ASurfaceTransactionStats_getASurfaceControls(ASurfaceTransactionStats* aSurfaceTransactionStats,
ASurfaceControl*** outASurfaceControls,
size_t* outASurfaceControlsSize) {
CHECK_NOT_NULL(aSurfaceTransactionStats);
CHECK_NOT_NULL(outASurfaceControls);
CHECK_NOT_NULL(outASurfaceControlsSize);
size_t size = aSurfaceTransactionStats->aSurfaceControlStats.size();
SurfaceControl** surfaceControls = new SurfaceControl*[size];
ASurfaceControl** aSurfaceControls = reinterpret_cast<ASurfaceControl**>(surfaceControls);
size_t i = 0;
for (auto& [aSurfaceControl, aSurfaceControlStats] : aSurfaceTransactionStats->aSurfaceControlStats) {
aSurfaceControls[i] = aSurfaceControl;
i++;
}
*outASurfaceControls = aSurfaceControls;
*outASurfaceControlsSize = size;
}
int64_t ASurfaceTransactionStats_getAcquireTime(ASurfaceTransactionStats* aSurfaceTransactionStats,
ASurfaceControl* aSurfaceControl) {
CHECK_NOT_NULL(aSurfaceTransactionStats);
CHECK_NOT_NULL(aSurfaceControl);
const auto& aSurfaceControlStats =
aSurfaceTransactionStats->aSurfaceControlStats.find(aSurfaceControl);
LOG_ALWAYS_FATAL_IF(
aSurfaceControlStats == aSurfaceTransactionStats->aSurfaceControlStats.end(),
"ASurfaceControl not found");
return ASurfaceControlStats_getAcquireTime(&aSurfaceControlStats->second);
}
int ASurfaceTransactionStats_getPreviousReleaseFenceFd(
ASurfaceTransactionStats* aSurfaceTransactionStats, ASurfaceControl* aSurfaceControl) {
CHECK_NOT_NULL(aSurfaceTransactionStats);
CHECK_NOT_NULL(aSurfaceControl);
LOG_ALWAYS_FATAL_IF(!aSurfaceTransactionStats->transactionCompleted,
"ASurfaceTransactionStats queried from an incomplete transaction callback");
const auto& aSurfaceControlStats =
aSurfaceTransactionStats->aSurfaceControlStats.find(aSurfaceControl);
LOG_ALWAYS_FATAL_IF(
aSurfaceControlStats == aSurfaceTransactionStats->aSurfaceControlStats.end(),
"ASurfaceControl not found");
auto& previousReleaseFence = aSurfaceControlStats->second.previousReleaseFence;
return (previousReleaseFence) ? previousReleaseFence->dup() : -1;
}
void ASurfaceTransactionStats_releaseASurfaceControls(ASurfaceControl** aSurfaceControls) {
CHECK_NOT_NULL(aSurfaceControls);
SurfaceControl** surfaceControls = reinterpret_cast<SurfaceControl**>(aSurfaceControls);
delete[] surfaceControls;
}
void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* aSurfaceTransaction, void* context,
ASurfaceTransaction_OnComplete func) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(func);
TransactionCompletedCallbackTakesContext callback = [func](void* callback_context,
nsecs_t latchTime,
const sp<Fence>& presentFence,
const std::vector<SurfaceControlStats>& surfaceControlStats) {
ASurfaceTransactionStats aSurfaceTransactionStats;
aSurfaceTransactionStats.latchTime = latchTime;
aSurfaceTransactionStats.presentFence = presentFence;
aSurfaceTransactionStats.transactionCompleted = true;
auto& aSurfaceControlStats = aSurfaceTransactionStats.aSurfaceControlStats;
for (const auto& [surfaceControl, latchTime, acquireTimeOrFence, presentFence,
previousReleaseFence, transformHint, frameEvents, ignore] : surfaceControlStats) {
ASurfaceControl* aSurfaceControl = reinterpret_cast<ASurfaceControl*>(surfaceControl.get());
aSurfaceControlStats[aSurfaceControl].acquireTimeOrFence = acquireTimeOrFence;
aSurfaceControlStats[aSurfaceControl].previousReleaseFence = previousReleaseFence;
}
(*func)(callback_context, &aSurfaceTransactionStats);
};
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
transaction->addTransactionCompletedCallback(callback, context);
}
void ASurfaceTransaction_reparent(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
ASurfaceControl* newParentASurfaceControl) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
sp<SurfaceControl> newParentSurfaceControl = ASurfaceControl_to_SurfaceControl(
newParentASurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
transaction->reparent(surfaceControl, newParentSurfaceControl);
}
void ASurfaceTransaction_setVisibility(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
int8_t visibility) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
switch (visibility) {
case ASURFACE_TRANSACTION_VISIBILITY_SHOW:
transaction->show(surfaceControl);
break;
case ASURFACE_TRANSACTION_VISIBILITY_HIDE:
transaction->hide(surfaceControl);
break;
default:
LOG_ALWAYS_FATAL("invalid visibility %d", visibility);
}
}
void ASurfaceTransaction_setZOrder(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
int32_t z_order) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
transaction->setLayer(surfaceControl, z_order);
}
void ASurfaceTransaction_setBuffer(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
AHardwareBuffer* buffer, int acquire_fence_fd) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
sp<GraphicBuffer> graphic_buffer(GraphicBuffer::fromAHardwareBuffer(buffer));
std::optional<sp<Fence>> fence = std::nullopt;
if (acquire_fence_fd != -1) {
fence = new Fence(acquire_fence_fd);
}
transaction->setBuffer(surfaceControl, graphic_buffer, fence);
}
void ASurfaceTransaction_setGeometry(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl, const ARect& source,
const ARect& destination, int32_t transform) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
CHECK_VALID_RECT(source);
CHECK_VALID_RECT(destination);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
Rect sourceRect = static_cast<const Rect&>(source);
Rect destRect = static_cast<const Rect&>(destination);
// Adjust the source so its top and left are not negative
sourceRect.left = std::max(sourceRect.left, 0);
sourceRect.top = std::max(sourceRect.top, 0);
if (!sourceRect.isValid()) {
sourceRect.makeInvalid();
}
transaction->setBufferCrop(surfaceControl, sourceRect);
transaction->setDestinationFrame(surfaceControl, destRect);
transaction->setTransform(surfaceControl, transform);
bool transformToInverseDisplay = (NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY & transform) ==
NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
transaction->setTransformToDisplayInverse(surfaceControl, transformToInverseDisplay);
}
void ASurfaceTransaction_setCrop(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl, const ARect& crop) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
CHECK_VALID_RECT(crop);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
transaction->setCrop(surfaceControl, static_cast<const Rect&>(crop));
}
void ASurfaceTransaction_setPosition(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl, int32_t x, int32_t y) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
transaction->setPosition(surfaceControl, x, y);
}
void ASurfaceTransaction_setBufferTransform(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl, int32_t transform) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
transaction->setTransform(surfaceControl, transform);
bool transformToInverseDisplay = (NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY & transform) ==
NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
transaction->setTransformToDisplayInverse(surfaceControl, transformToInverseDisplay);
}
void ASurfaceTransaction_setScale(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl, float xScale, float yScale) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
LOG_ALWAYS_FATAL_IF(xScale < 0, "negative value passed in for xScale");
LOG_ALWAYS_FATAL_IF(yScale < 0, "negative value passed in for yScale");
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
transaction->setMatrix(surfaceControl, xScale, 0, 0, yScale);
}
void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
int8_t transparency) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
uint32_t flags = (transparency == ASURFACE_TRANSACTION_TRANSPARENCY_OPAQUE) ?
layer_state_t::eLayerOpaque : 0;
transaction->setFlags(surfaceControl, flags, layer_state_t::eLayerOpaque);
}
void ASurfaceTransaction_setDamageRegion(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
const ARect rects[], uint32_t count) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
Region region;
for (uint32_t i = 0; i < count; ++i) {
region.orSelf(static_cast<const Rect&>(rects[i]));
}
// Hardware composer interprets a DamageRegion with a single Rect of {0,0,0,0} to be an
// undamaged region and {0,0,-1,-1} to be a fully damaged buffer. This is a confusing
// distinction for a public api. Instead, default both cases to be a fully damaged buffer.
if (count == 1 && region.getBounds().isEmpty()) {
transaction->setSurfaceDamageRegion(surfaceControl, Region::INVALID_REGION);
return;
}
transaction->setSurfaceDamageRegion(surfaceControl, region);
}
void ASurfaceTransaction_setDesiredPresentTime(ASurfaceTransaction* aSurfaceTransaction,
int64_t desiredPresentTime) {
CHECK_NOT_NULL(aSurfaceTransaction);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
transaction->setDesiredPresentTime(static_cast<nsecs_t>(desiredPresentTime));
}
void ASurfaceTransaction_setBufferAlpha(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
float alpha) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
LOG_ALWAYS_FATAL_IF(alpha < 0.0 || alpha > 1.0, "invalid alpha");
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
transaction->setAlpha(surfaceControl, alpha);
}
void ASurfaceTransaction_setBufferDataSpace(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
ADataSpace aDataSpace) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
transaction->setDataspace(surfaceControl, static_cast<ui::Dataspace>(aDataSpace));
}
void ASurfaceTransaction_setHdrMetadata_smpte2086(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
struct AHdrMetadata_smpte2086* metadata) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
HdrMetadata hdrMetadata;
if (metadata) {
hdrMetadata.smpte2086.displayPrimaryRed.x = metadata->displayPrimaryRed.x;
hdrMetadata.smpte2086.displayPrimaryRed.y = metadata->displayPrimaryRed.y;
hdrMetadata.smpte2086.displayPrimaryGreen.x = metadata->displayPrimaryGreen.x;
hdrMetadata.smpte2086.displayPrimaryGreen.y = metadata->displayPrimaryGreen.y;
hdrMetadata.smpte2086.displayPrimaryBlue.x = metadata->displayPrimaryBlue.x;
hdrMetadata.smpte2086.displayPrimaryBlue.y = metadata->displayPrimaryBlue.y;
hdrMetadata.smpte2086.whitePoint.x = metadata->whitePoint.x;
hdrMetadata.smpte2086.whitePoint.y = metadata->whitePoint.y;
hdrMetadata.smpte2086.minLuminance = metadata->minLuminance;
hdrMetadata.smpte2086.maxLuminance = metadata->maxLuminance;
hdrMetadata.validTypes |= HdrMetadata::SMPTE2086;
} else {
hdrMetadata.validTypes &= ~HdrMetadata::SMPTE2086;
}
transaction->setHdrMetadata(surfaceControl, hdrMetadata);
}
void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
struct AHdrMetadata_cta861_3* metadata) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
HdrMetadata hdrMetadata;
if (metadata) {
hdrMetadata.cta8613.maxContentLightLevel = metadata->maxContentLightLevel;
hdrMetadata.cta8613.maxFrameAverageLightLevel = metadata->maxFrameAverageLightLevel;
hdrMetadata.validTypes |= HdrMetadata::CTA861_3;
} else {
hdrMetadata.validTypes &= ~HdrMetadata::CTA861_3;
}
transaction->setHdrMetadata(surfaceControl, hdrMetadata);
}
void ASurfaceTransaction_setExtendedRangeBrightness(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
float currentBufferRatio, float desiredRatio) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
if (!isfinite(currentBufferRatio) || currentBufferRatio < 1.0f) {
LOG_ALWAYS_FATAL("setExtendedRangeBrightness, currentBufferRatio %f isn't finite or >= "
"1.0f",
currentBufferRatio);
return;
}
if (!isfinite(desiredRatio) || desiredRatio < 1.0f) {
LOG_ALWAYS_FATAL("setExtendedRangeBrightness, desiredRatio %f isn't finite or >= 1.0f",
desiredRatio);
return;
}
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
transaction->setExtendedRangeBrightness(surfaceControl, currentBufferRatio, desiredRatio);
}
void ASurfaceTransaction_setDesiredHdrHeadroom(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
float desiredRatio) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
if (!isfinite(desiredRatio) || (desiredRatio < 1.0f && desiredRatio > 0.0f)) {
LOG_ALWAYS_FATAL("setDesiredHdrHeadroom, desiredRatio isn't finite && >= 1.0f or 0, got %f",
desiredRatio);
return;
}
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
transaction->setDesiredHdrHeadroom(surfaceControl, desiredRatio);
}
void ASurfaceTransaction_setColor(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
float r, float g, float b, float alpha,
ADataSpace dataspace) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
half3 color;
color.r = r;
color.g = g;
color.b = b;
transaction->setBackgroundColor(surfaceControl, color, alpha,
static_cast<ui::Dataspace>(dataspace));
}
void ASurfaceTransaction_setFrameRate(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl, float frameRate,
int8_t compatibility) {
ASurfaceTransaction_setFrameRateWithChangeStrategy(
aSurfaceTransaction, aSurfaceControl, frameRate, compatibility,
ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
}
void ASurfaceTransaction_setFrameRateWithChangeStrategy(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
float frameRate, int8_t compatibility,
int8_t changeFrameRateStrategy) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
transaction->setFrameRate(surfaceControl, frameRate, compatibility, changeFrameRateStrategy);
}
void ASurfaceTransaction_clearFrameRate(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
transaction->setFrameRate(surfaceControl, 0, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT,
ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
}
void ASurfaceTransaction_setEnableBackPressure(ASurfaceTransaction* aSurfaceTransaction,
ASurfaceControl* aSurfaceControl,
bool enableBackpressure) {
CHECK_NOT_NULL(aSurfaceControl);
CHECK_NOT_NULL(aSurfaceTransaction);
sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
const uint32_t flags = enableBackpressure ?
layer_state_t::eEnableBackpressure : 0;
transaction->setFlags(surfaceControl, flags, layer_state_t::eEnableBackpressure);
}
void ASurfaceTransaction_setOnCommit(ASurfaceTransaction* aSurfaceTransaction, void* context,
ASurfaceTransaction_OnCommit func) {
CHECK_NOT_NULL(aSurfaceTransaction);
CHECK_NOT_NULL(func);
TransactionCompletedCallbackTakesContext callback =
[func](void* callback_context, nsecs_t latchTime, const sp<Fence>& /* presentFence */,
const std::vector<SurfaceControlStats>& surfaceControlStats) {
ASurfaceTransactionStats aSurfaceTransactionStats;
aSurfaceTransactionStats.latchTime = latchTime;
aSurfaceTransactionStats.transactionCompleted = false;
auto& aSurfaceControlStats = aSurfaceTransactionStats.aSurfaceControlStats;
for (const auto& [surfaceControl, latchTime, acquireTimeOrFence, presentFence,
previousReleaseFence, transformHint, frameEvents, ignore] :
surfaceControlStats) {
ASurfaceControl* aSurfaceControl =
reinterpret_cast<ASurfaceControl*>(surfaceControl.get());
aSurfaceControlStats[aSurfaceControl].acquireTimeOrFence = acquireTimeOrFence;
}
(*func)(callback_context, &aSurfaceTransactionStats);
};
Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
transaction->addTransactionCommittedCallback(callback, context);
}
void ASurfaceTransaction_setFrameTimeline(ASurfaceTransaction* aSurfaceTransaction,
AVsyncId vsyncId) {
CHECK_NOT_NULL(aSurfaceTransaction);
const auto startTime = AChoreographer_getStartTimeNanosForVsyncId(vsyncId);
FrameTimelineInfo ftInfo;
ftInfo.vsyncId = vsyncId;
ftInfo.startTimeNanos = startTime;
ASurfaceTransaction_to_Transaction(aSurfaceTransaction)->setFrameTimelineInfo(ftInfo);
}