diff options
55 files changed, 881 insertions, 1320 deletions
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index 1a932c3d04..4f7cdf3e5e 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -4,13 +4,16 @@ clang_format = true [Builtin Hooks Options] # Only turn on clang-format check for the following subfolders. clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp + include/input/ libs/binder/ndk/ libs/graphicsenv/ libs/gui/ + libs/input/ libs/renderengine/ libs/ui/ libs/vr/ services/bufferhub/ + services/inputflinger/ services/surfaceflinger/ services/vr/ diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl index 26e9984f11..d99bcc8d13 100644 --- a/cmds/installd/binder/android/os/IInstalld.aidl +++ b/cmds/installd/binder/android/os/IInstalld.aidl @@ -127,4 +127,6 @@ interface IInstalld { const int FLAG_USE_QUOTA = 0x1000; const int FLAG_FORCE = 0x2000; + + const int FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES = 0x20000; } diff --git a/include/android/surface_control.h b/include/android/surface_control.h index ef2ad9998c..abb8368069 100644 --- a/include/android/surface_control.h +++ b/include/android/surface_control.h @@ -130,7 +130,7 @@ int64_t ASurfaceTransactionStats_getLatchTime(ASurfaceTransactionStats* surface_ /** * Returns a sync fence that signals when the transaction has been presented. * The recipient of the callback takes ownership of the fence and is responsible for closing - * it. + * it. If a device does not support present fences, a -1 will be returned. */ int ASurfaceTransactionStats_getPresentFenceFd(ASurfaceTransactionStats* surface_transaction_stats) __INTRODUCED_IN(29); diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 458961b70d..c389d18243 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -616,7 +616,7 @@ bool Parcel::replaceCallingWorkSourceUid(uid_t uid) return err == NO_ERROR; } -uid_t Parcel::readCallingWorkSourceUid() +uid_t Parcel::readCallingWorkSourceUid() const { if (!mRequestHeaderPresent) { return IPCThreadState::kUnsetWorkSource; diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h index 0cdabb0265..0046e3ae85 100644 --- a/libs/binder/include/binder/Parcel.h +++ b/libs/binder/include/binder/Parcel.h @@ -399,7 +399,7 @@ public: bool replaceCallingWorkSourceUid(uid_t uid); // Returns the work source provided by the caller. This can only be trusted for trusted calling // uid. - uid_t readCallingWorkSourceUid(); + uid_t readCallingWorkSourceUid() const; void readRequestHeaders() const; private: diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp index 5fd4a95d7b..41cbde1c18 100644 --- a/libs/cputimeinstate/cputimeinstate.cpp +++ b/libs/cputimeinstate/cputimeinstate.cpp @@ -23,6 +23,7 @@ #include <inttypes.h> #include <mutex> +#include <optional> #include <set> #include <string> #include <unordered_map> @@ -62,19 +63,20 @@ static std::vector<std::vector<uint32_t>> gPolicyCpus; static std::set<uint32_t> gAllFreqs; static unique_fd gMapFd; -static bool readNumbersFromFile(const std::string &path, std::vector<uint32_t> *out) { +static std::optional<std::vector<uint32_t>> readNumbersFromFile(const std::string &path) { std::string data; - if (!android::base::ReadFileToString(path, &data)) return false; + if (!android::base::ReadFileToString(path, &data)) return {}; auto strings = android::base::Split(data, " \n"); + std::vector<uint32_t> ret; for (const auto &s : strings) { if (s.empty()) continue; uint32_t n; - if (!android::base::ParseUint(s, &n)) return false; - out->emplace_back(n); + if (!android::base::ParseUint(s, &n)) return {}; + ret.emplace_back(n); } - return true; + return ret; } static int isPolicyFile(const struct dirent *d) { @@ -111,20 +113,22 @@ static bool initGlobals() { for (const auto &name : {"available", "boost"}) { std::string path = StringPrintf("%s/%s/scaling_%s_frequencies", basepath, policy.c_str(), name); - if (!readNumbersFromFile(path, &freqs)) return false; + auto nums = readNumbersFromFile(path); + if (!nums) return false; + freqs.insert(freqs.end(), nums->begin(), nums->end()); } std::sort(freqs.begin(), freqs.end()); gPolicyFreqs.emplace_back(freqs); for (auto freq : freqs) gAllFreqs.insert(freq); - std::vector<uint32_t> cpus; std::string path = StringPrintf("%s/%s/%s", basepath, policy.c_str(), "related_cpus"); - if (!readNumbersFromFile(path, &cpus)) return false; - gPolicyCpus.emplace_back(cpus); + auto cpus = readNumbersFromFile(path); + if (!cpus) return false; + gPolicyCpus.emplace_back(*cpus); } - gMapFd = unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times")}; + gMapFd = unique_fd{bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times_map")}; if (gMapFd < 0) return false; gInitialized = true; @@ -151,17 +155,15 @@ bool startTrackingUidCpuFreqTimes() { } // Retrieve the times in ns that uid spent running at each CPU frequency and store in freqTimes. -// Returns false on error. Otherwise, returns true and populates freqTimes with a vector of vectors -// using the format: +// Return contains no value on error, otherwise it contains a vector of vectors using the format: // [[t0_0, t0_1, ...], // [t1_0, t1_1, ...], ...] // where ti_j is the ns that uid spent running on the ith cluster at that cluster's jth lowest freq. -bool getUidCpuFreqTimes(uint32_t uid, std::vector<std::vector<uint64_t>> *freqTimes) { - if (!gInitialized && !initGlobals()) return false; +std::optional<std::vector<std::vector<uint64_t>>> getUidCpuFreqTimes(uint32_t uid) { + if (!gInitialized && !initGlobals()) return {}; time_key_t key = {.uid = uid, .freq = 0}; - freqTimes->clear(); - freqTimes->resize(gNPolicies); + std::vector<std::vector<uint64_t>> out(gNPolicies); std::vector<uint32_t> idxs(gNPolicies, 0); val_t value; @@ -172,32 +174,32 @@ bool getUidCpuFreqTimes(uint32_t uid, std::vector<std::vector<uint64_t>> *freqTi if (errno == ENOENT) memset(&value.ar, 0, sizeof(value.ar)); else - return false; + return {}; } for (uint32_t i = 0; i < gNPolicies; ++i) { if (idxs[i] == gPolicyFreqs[i].size() || freq != gPolicyFreqs[i][idxs[i]]) continue; uint64_t time = 0; for (uint32_t cpu : gPolicyCpus[i]) time += value.ar[cpu]; idxs[i] += 1; - (*freqTimes)[i].emplace_back(time); + out[i].emplace_back(time); } } - return true; + return out; } // Retrieve the times in ns that each uid spent running at each CPU freq and store in freqTimeMap. -// Returns false on error. Otherwise, returns true and populates freqTimeMap with a map from uids to -// vectors of vectors using the format: +// Return contains no value on error, otherwise it contains a map from uids to vectors of vectors +// using the format: // { uid0 -> [[t0_0_0, t0_0_1, ...], [t0_1_0, t0_1_1, ...], ...], // uid1 -> [[t1_0_0, t1_0_1, ...], [t1_1_0, t1_1_1, ...], ...], ... } // where ti_j_k is the ns uid i spent running on the jth cluster at the cluster's kth lowest freq. -bool getUidsCpuFreqTimes( - std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>> *freqTimeMap) { - if (!gInitialized && !initGlobals()) return false; +std::optional<std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>>> +getUidsCpuFreqTimes() { + if (!gInitialized && !initGlobals()) return {}; - int fd = bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times"); - if (fd < 0) return false; + int fd = bpf_obj_get(BPF_FS_PATH "map_time_in_state_uid_times_map"); + if (fd < 0) return {}; BpfMap<time_key_t, val_t> m(fd); std::vector<std::unordered_map<uint32_t, uint32_t>> policyFreqIdxs; @@ -206,25 +208,26 @@ bool getUidsCpuFreqTimes( for (size_t j = 0; j < gPolicyFreqs[i].size(); ++j) freqIdxs[gPolicyFreqs[i][j]] = j; policyFreqIdxs.emplace_back(freqIdxs); } - - auto fn = [freqTimeMap, &policyFreqIdxs](const time_key_t &key, const val_t &val, + std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>> map; + auto fn = [&map, &policyFreqIdxs](const time_key_t &key, const val_t &val, const BpfMap<time_key_t, val_t> &) { - if (freqTimeMap->find(key.uid) == freqTimeMap->end()) { - (*freqTimeMap)[key.uid].resize(gNPolicies); + if (map.find(key.uid) == map.end()) { + map[key.uid].resize(gNPolicies); for (uint32_t i = 0; i < gNPolicies; ++i) { - (*freqTimeMap)[key.uid][i].resize(gPolicyFreqs[i].size(), 0); + map[key.uid][i].resize(gPolicyFreqs[i].size(), 0); } } for (size_t policy = 0; policy < gNPolicies; ++policy) { for (const auto &cpu : gPolicyCpus[policy]) { auto freqIdx = policyFreqIdxs[policy][key.freq]; - (*freqTimeMap)[key.uid][policy][freqIdx] += val.ar[cpu]; + map[key.uid][policy][freqIdx] += val.ar[cpu]; } } return android::netdutils::status::ok; }; - return isOk(m.iterateWithValue(fn)); + if (isOk(m.iterateWithValue(fn))) return map; + return {}; } // Clear all time in state data for a given uid. Returns false on error, true otherwise. diff --git a/libs/cputimeinstate/cputimeinstate.h b/libs/cputimeinstate/cputimeinstate.h index 9f6103ed9b..d7b45870ac 100644 --- a/libs/cputimeinstate/cputimeinstate.h +++ b/libs/cputimeinstate/cputimeinstate.h @@ -23,8 +23,9 @@ namespace android { namespace bpf { bool startTrackingUidCpuFreqTimes(); -bool getUidCpuFreqTimes(unsigned int uid, std::vector<std::vector<uint64_t>> *freqTimes); -bool getUidsCpuFreqTimes(std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>> *tisMap); +std::optional<std::vector<std::vector<uint64_t>>> getUidCpuFreqTimes(uint32_t uid); +std::optional<std::unordered_map<uint32_t, std::vector<std::vector<uint64_t>>>> + getUidsCpuFreqTimes(); bool clearUidCpuFreqTimes(unsigned int uid); } // namespace bpf diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp index 9837865dfb..d4b87386e0 100644 --- a/libs/cputimeinstate/testtimeinstate.cpp +++ b/libs/cputimeinstate/testtimeinstate.cpp @@ -12,45 +12,46 @@ namespace bpf { using std::vector; TEST(TimeInStateTest, SingleUid) { - vector<vector<uint64_t>> times; - ASSERT_TRUE(getUidCpuFreqTimes(0, ×)); - EXPECT_FALSE(times.empty()); + auto times = getUidCpuFreqTimes(0); + ASSERT_TRUE(times.has_value()); + EXPECT_FALSE(times->empty()); } TEST(TimeInStateTest, AllUid) { vector<size_t> sizes; - std::unordered_map<uint32_t, vector<vector<uint64_t>>> map; - ASSERT_TRUE(getUidsCpuFreqTimes(&map)); + auto map = getUidsCpuFreqTimes(); + ASSERT_TRUE(map.has_value()); - ASSERT_FALSE(map.empty()); + ASSERT_FALSE(map->empty()); - auto firstEntry = map.begin()->second; + auto firstEntry = map->begin()->second; for (const auto &subEntry : firstEntry) sizes.emplace_back(subEntry.size()); - for (const auto &vec : map) { + for (const auto &vec : *map) { ASSERT_EQ(vec.second.size(), sizes.size()); for (size_t i = 0; i < vec.second.size(); ++i) ASSERT_EQ(vec.second[i].size(), sizes[i]); } } TEST(TimeInStateTest, RemoveUid) { - vector<vector<uint64_t>> times, times2; - ASSERT_TRUE(getUidCpuFreqTimes(0, ×)); - ASSERT_FALSE(times.empty()); + auto times = getUidCpuFreqTimes(0); + ASSERT_TRUE(times.has_value()); + ASSERT_FALSE(times->empty()); uint64_t sum = 0; - for (size_t i = 0; i < times.size(); ++i) { - for (auto x : times[i]) sum += x; + for (size_t i = 0; i < times->size(); ++i) { + for (auto x : (*times)[i]) sum += x; } ASSERT_GT(sum, (uint64_t)0); ASSERT_TRUE(clearUidCpuFreqTimes(0)); - ASSERT_TRUE(getUidCpuFreqTimes(0, ×2)); - ASSERT_EQ(times2.size(), times.size()); - for (size_t i = 0; i < times.size(); ++i) { - ASSERT_EQ(times2[i].size(), times[i].size()); - for (size_t j = 0; j < times[i].size(); ++j) ASSERT_LE(times2[i][j], times[i][j]); + auto times2 = getUidCpuFreqTimes(0); + ASSERT_TRUE(times2.has_value()); + ASSERT_EQ(times2->size(), times->size()); + for (size_t i = 0; i < times->size(); ++i) { + ASSERT_EQ((*times2)[i].size(), (*times)[i].size()); + for (size_t j = 0; j < (*times)[i].size(); ++j) ASSERT_LE((*times2)[i][j], (*times)[i][j]); } } diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 34575f5d47..b2a7557588 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -15,6 +15,10 @@ cc_library_headers { name: "libgui_headers", vendor_available: true, export_include_dirs: ["include"], + + // we must build this module to get the required header as that is generated + export_shared_lib_headers: [ "android.hidl.token@1.0-utils" ], + shared_libs: [ "android.hidl.token@1.0-utils" ], } cc_library_shared { diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 9c311a314f..b9a4749ccd 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -1132,9 +1132,6 @@ int BufferQueueProducer::query(int what, int *outValue) { case NATIVE_WINDOW_CONSUMER_IS_PROTECTED: value = static_cast<int32_t>(mCore->mConsumerIsProtected); break; - case NATIVE_WINDOW_MAX_BUFFER_COUNT: - value = static_cast<int32_t>(mCore->mMaxBufferCount); - break; default: return BAD_VALUE; } @@ -1199,6 +1196,7 @@ status_t BufferQueueProducer::connect(const sp<IProducerListener>& listener, static_cast<uint32_t>(mCore->mQueue.size()); output->nextFrameNumber = mCore->mFrameCounter + 1; output->bufferReplaced = false; + output->maxBufferCount = mCore->mMaxBufferCount; if (listener != nullptr) { // Set up a death notification so that we can disconnect diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index 0e03b7d393..9db0a7ca33 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -1141,12 +1141,8 @@ status_t IGraphicBufferProducer::QueueBufferInput::unflatten( // ---------------------------------------------------------------------------- constexpr size_t IGraphicBufferProducer::QueueBufferOutput::minFlattenedSize() { - return sizeof(width) + - sizeof(height) + - sizeof(transformHint) + - sizeof(numPendingBuffers) + - sizeof(nextFrameNumber) + - sizeof(bufferReplaced); + return sizeof(width) + sizeof(height) + sizeof(transformHint) + sizeof(numPendingBuffers) + + sizeof(nextFrameNumber) + sizeof(bufferReplaced) + sizeof(maxBufferCount); } size_t IGraphicBufferProducer::QueueBufferOutput::getFlattenedSize() const { @@ -1170,6 +1166,7 @@ status_t IGraphicBufferProducer::QueueBufferOutput::flatten( FlattenableUtils::write(buffer, size, numPendingBuffers); FlattenableUtils::write(buffer, size, nextFrameNumber); FlattenableUtils::write(buffer, size, bufferReplaced); + FlattenableUtils::write(buffer, size, maxBufferCount); return frameTimestamps.flatten(buffer, size, fds, count); } @@ -1187,6 +1184,7 @@ status_t IGraphicBufferProducer::QueueBufferOutput::unflatten( FlattenableUtils::read(buffer, size, numPendingBuffers); FlattenableUtils::read(buffer, size, nextFrameNumber); FlattenableUtils::read(buffer, size, bufferReplaced); + FlattenableUtils::read(buffer, size, maxBufferCount); return frameTimestamps.unflatten(buffer, size, fds, count); } diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index e6eb327c6f..2e8a5d005b 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -96,6 +96,7 @@ Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controll mConnectedToCpu = false; mProducerControlledByApp = controlledByApp; mSwapIntervalZero = false; + mMaxBufferCount = 0; } Surface::~Surface() { @@ -961,6 +962,10 @@ int Surface::query(int what, int* value) const { *value = static_cast<int>(mDataSpace); return NO_ERROR; } + case NATIVE_WINDOW_MAX_BUFFER_COUNT: { + *value = mMaxBufferCount; + return NO_ERROR; + } } } return mGraphicBufferProducer->query(what, value); @@ -1298,6 +1303,7 @@ int Surface::connect( mDefaultWidth = output.width; mDefaultHeight = output.height; mNextFrameNumber = output.nextFrameNumber; + mMaxBufferCount = output.maxBufferCount; // Ignore transform hint if sticky transform is set or transform to display inverse flag is // set. Transform hint should be ignored if the client is expected to always submit buffers diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index d6f88fc7a4..c59fddfb9d 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -322,10 +322,99 @@ SurfaceComposerClient::Transaction::Transaction(const Transaction& other) mTransactionNestCount(other.mTransactionNestCount), mAnimation(other.mAnimation), mEarlyWakeup(other.mEarlyWakeup), + mContainsBuffer(other.mContainsBuffer), mDesiredPresentTime(other.mDesiredPresentTime) { mDisplayStates = other.mDisplayStates; mComposerStates = other.mComposerStates; mInputWindowCommands = other.mInputWindowCommands; + mListenerCallbacks = other.mListenerCallbacks; +} + +std::unique_ptr<SurfaceComposerClient::Transaction> +SurfaceComposerClient::Transaction::createFromParcel(const Parcel* parcel) { + auto transaction = std::make_unique<Transaction>(); + if (transaction->readFromParcel(parcel) == NO_ERROR) { + return transaction; + } + return nullptr; +} + +status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel) { + const uint32_t forceSynchronous = parcel->readUint32(); + const uint32_t transactionNestCount = parcel->readUint32(); + const bool animation = parcel->readBool(); + const bool earlyWakeup = parcel->readBool(); + const bool containsBuffer = parcel->readBool(); + const int64_t desiredPresentTime = parcel->readInt64(); + + size_t count = static_cast<size_t>(parcel->readUint32()); + if (count > parcel->dataSize()) { + return BAD_VALUE; + } + SortedVector<DisplayState> displayStates; + displayStates.setCapacity(count); + for (size_t i = 0; i < count; i++) { + DisplayState displayState; + if (displayState.read(*parcel) == BAD_VALUE) { + return BAD_VALUE; + } + displayStates.add(displayState); + } + + count = static_cast<size_t>(parcel->readUint32()); + if (count > parcel->dataSize()) { + return BAD_VALUE; + } + std::unordered_map<sp<SurfaceControl>, ComposerState, SCHash> composerStates; + composerStates.reserve(count); + for (size_t i = 0; i < count; i++) { + sp<SurfaceControl> surfaceControl = SurfaceControl::readFromParcel(parcel); + + ComposerState composerState; + if (composerState.read(*parcel) == BAD_VALUE) { + return BAD_VALUE; + } + composerStates[surfaceControl] = composerState; + } + + InputWindowCommands inputWindowCommands; + inputWindowCommands.read(*parcel); + + // Parsing was successful. Update the object. + mForceSynchronous = forceSynchronous; + mTransactionNestCount = transactionNestCount; + mAnimation = animation; + mEarlyWakeup = earlyWakeup; + mContainsBuffer = containsBuffer; + mDesiredPresentTime = desiredPresentTime; + mDisplayStates = displayStates; + mComposerStates = composerStates; + mInputWindowCommands = inputWindowCommands; + // listener callbacks contain function pointer addresses and may not be safe to parcel. + mListenerCallbacks.clear(); + return NO_ERROR; +} + +status_t SurfaceComposerClient::Transaction::writeToParcel(Parcel* parcel) const { + parcel->writeUint32(mForceSynchronous); + parcel->writeUint32(mTransactionNestCount); + parcel->writeBool(mAnimation); + parcel->writeBool(mEarlyWakeup); + parcel->writeBool(mContainsBuffer); + parcel->writeInt64(mDesiredPresentTime); + parcel->writeUint32(static_cast<uint32_t>(mDisplayStates.size())); + for (auto const& displayState : mDisplayStates) { + displayState.write(*parcel); + } + + parcel->writeUint32(static_cast<uint32_t>(mComposerStates.size())); + for (auto const& [surfaceControl, composerState] : mComposerStates) { + surfaceControl->writeToParcel(parcel); + composerState.write(*parcel); + } + + mInputWindowCommands.write(*parcel); + return NO_ERROR; } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Transaction&& other) { @@ -336,7 +425,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr mComposerStates[kv.first].state.merge(kv.second.state); } } - other.mComposerStates.clear(); for (auto const& state : other.mDisplayStates) { ssize_t index = mDisplayStates.indexOf(state); @@ -346,7 +434,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr mDisplayStates.editItemAt(static_cast<size_t>(index)).merge(state); } } - other.mDisplayStates.clear(); for (const auto& [listener, callbackInfo] : other.mListenerCallbacks) { auto& [callbackIds, surfaceControls] = callbackInfo; @@ -357,17 +444,27 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr .surfaceControls.insert(std::make_move_iterator(surfaceControls.begin()), std::make_move_iterator(surfaceControls.end())); } - other.mListenerCallbacks.clear(); mInputWindowCommands.merge(other.mInputWindowCommands); - other.mInputWindowCommands.clear(); mContainsBuffer = other.mContainsBuffer; - other.mContainsBuffer = false; - + other.clear(); return *this; } +void SurfaceComposerClient::Transaction::clear() { + mComposerStates.clear(); + mDisplayStates.clear(); + mListenerCallbacks.clear(); + mInputWindowCommands.clear(); + mContainsBuffer = false; + mForceSynchronous = 0; + mTransactionNestCount = 0; + mAnimation = false; + mEarlyWakeup = false; + mDesiredPresentTime = -1; +} + void SurfaceComposerClient::doDropReferenceTransaction(const sp<IBinder>& handle, const sp<ISurfaceComposerClient>& client) { sp<ISurfaceComposer> sf(ComposerService::getComposerService()); @@ -623,6 +720,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setRelat layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; + return *this; } s->what |= layer_state_t::eRelativeLayerChanged; s->what &= ~layer_state_t::eLayerChanged; @@ -1052,6 +1150,7 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachCh layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; + return *this; } s->what |= layer_state_t::eDetachChildren; diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index 55488dad0b..b9defdd120 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -71,14 +71,6 @@ SurfaceControl::~SurfaceControl() release(); } -void SurfaceControl::destroy() -{ - if (isValid()) { - SurfaceComposerClient::Transaction().reparent(this, nullptr).apply(); - } - release(); -} - void SurfaceControl::release() { // Trigger an IPC now, to make sure things @@ -186,8 +178,7 @@ void SurfaceControl::writeToParcel(Parcel* parcel) parcel->writeStrongBinder(IGraphicBufferProducer::asBinder(mGraphicBufferProducer)); } -sp<SurfaceControl> SurfaceControl::readFromParcel(Parcel* parcel) -{ +sp<SurfaceControl> SurfaceControl::readFromParcel(const Parcel* parcel) { sp<IBinder> client = parcel->readStrongBinder(); sp<IBinder> handle = parcel->readStrongBinder(); if (client == nullptr || handle == nullptr) diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h index 3dde8c8c80..6e002dd505 100644 --- a/libs/gui/include/gui/IGraphicBufferProducer.h +++ b/libs/gui/include/gui/IGraphicBufferProducer.h @@ -412,6 +412,7 @@ public: uint64_t nextFrameNumber{0}; FrameEventHistoryDelta frameTimestamps; bool bufferReplaced{false}; + int maxBufferCount{0}; }; virtual status_t queueBuffer(int slot, const QueueBufferInput& input, diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 0c471bb701..80469dfeaf 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -465,6 +465,7 @@ protected: bool mReportRemovedBuffers = false; std::vector<sp<GraphicBuffer>> mRemovedBuffers; + int mMaxBufferCount; }; } // namespace android diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 0e17c7b015..4dda97f5e1 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -285,7 +285,7 @@ public: std::unordered_set<sp<SurfaceControl>, SCHash> surfaceControls; }; - class Transaction { + class Transaction : Parcelable { std::unordered_map<sp<SurfaceControl>, ComposerState, SCHash> mComposerStates; SortedVector<DisplayState > mDisplayStates; std::unordered_map<sp<ITransactionCompletedListener>, CallbackInfo, TCLHash> @@ -325,6 +325,15 @@ public: virtual ~Transaction() = default; Transaction(Transaction const& other); + // Factory method that creates a new Transaction instance from the parcel. + static std::unique_ptr<Transaction> createFromParcel(const Parcel* parcel); + + status_t writeToParcel(Parcel* parcel) const override; + status_t readFromParcel(const Parcel* parcel) override; + + // Clears the contents of the transaction without applying it. + void clear(); + status_t apply(bool synchronous = false); // Merge another transaction in to this one, clearing other // as if it had been applied. diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h index 23bfc0256b..ae4a14690f 100644 --- a/libs/gui/include/gui/SurfaceControl.h +++ b/libs/gui/include/gui/SurfaceControl.h @@ -44,7 +44,7 @@ class SurfaceComposerClient; class SurfaceControl : public RefBase { public: - static sp<SurfaceControl> readFromParcel(Parcel* parcel); + static sp<SurfaceControl> readFromParcel(const Parcel* parcel); void writeToParcel(Parcel* parcel); static bool isValid(const sp<SurfaceControl>& surface) { @@ -81,7 +81,7 @@ public: status_t getLayerFrameStats(FrameStats* outStats) const; sp<SurfaceComposerClient> getClient() const; - + explicit SurfaceControl(const sp<SurfaceControl>& other); SurfaceControl(const sp<SurfaceComposerClient>& client, const sp<IBinder>& handle, diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp index 119e888edb..98dc1e6337 100644 --- a/libs/gui/tests/BufferQueue_test.cpp +++ b/libs/gui/tests/BufferQueue_test.cpp @@ -169,6 +169,18 @@ TEST_F(BufferQueueTest, DISABLED_BufferQueueInAnotherProcess) { ASSERT_EQ(OK, item.mGraphicBuffer->unlock()); } +TEST_F(BufferQueueTest, GetMaxBufferCountInQueueBufferOutput_Succeeds) { + createBufferQueue(); + sp<DummyConsumer> dc(new DummyConsumer); + mConsumer->consumerConnect(dc, false); + int bufferCount = 50; + mConsumer->setMaxBufferCount(bufferCount); + + IGraphicBufferProducer::QueueBufferOutput output; + mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false, &output); + ASSERT_EQ(output.maxBufferCount, bufferCount); +} + TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) { createBufferQueue(); sp<DummyConsumer> dc(new DummyConsumer); diff --git a/libs/gui/tests/RegionSampling_test.cpp b/libs/gui/tests/RegionSampling_test.cpp index d33ecfbdb9..c9de37d957 100644 --- a/libs/gui/tests/RegionSampling_test.cpp +++ b/libs/gui/tests/RegionSampling_test.cpp @@ -297,4 +297,70 @@ TEST_F(RegionSamplingTest, DISABLED_CollectsLumaFromTwoRegions) { composer->removeRegionSamplingListener(grayListener); } +TEST_F(RegionSamplingTest, DISABLED_TestIfInvalidInputParameters) { + sp<ISurfaceComposer> composer = ComposerService::getComposerService(); + sp<Listener> listener = new Listener(); + const Rect sampleArea{100, 100, 200, 200}; + // Invalid input sampleArea + EXPECT_EQ(BAD_VALUE, + composer->addRegionSamplingListener(Rect::INVALID_RECT, mTopLayer->getHandle(), + listener)); + listener->reset(); + // Invalid input binder + EXPECT_EQ(NO_ERROR, composer->addRegionSamplingListener(sampleArea, NULL, listener)); + // Invalid input listener + EXPECT_EQ(BAD_VALUE, + composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), NULL)); + EXPECT_EQ(BAD_VALUE, composer->removeRegionSamplingListener(NULL)); + // remove the listener + composer->removeRegionSamplingListener(listener); +} + +TEST_F(RegionSamplingTest, DISABLED_TestCallbackAfterRemoveListener) { + fill_render(rgba_green); + sp<ISurfaceComposer> composer = ComposerService::getComposerService(); + sp<Listener> listener = new Listener(); + const Rect sampleArea{100, 100, 200, 200}; + composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener); + fill_render(rgba_green); + + EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_NEAR(listener->luma(), luma_green, error_margin); + + listener->reset(); + composer->removeRegionSamplingListener(listener); + fill_render(rgba_green); + EXPECT_FALSE(listener->wait_event(100ms)) + << "callback should stop after remove the region sampling listener"; +} + +TEST_F(RegionSamplingTest, DISABLED_CollectsLumaFromMovingLayer) { + sp<ISurfaceComposer> composer = ComposerService::getComposerService(); + sp<Listener> listener = new Listener(); + Rect sampleArea{100, 100, 200, 200}; + + // Test: listener in (100, 100). See layer before move, no layer after move. + fill_render(rgba_blue); + composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener); + EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_NEAR(listener->luma(), luma_blue, error_margin); + listener->reset(); + SurfaceComposerClient::Transaction{}.setPosition(mContentLayer, 600, 600).apply(); + EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_NEAR(listener->luma(), luma_gray, error_margin); + composer->removeRegionSamplingListener(listener); + + // Test: listener offset to (600, 600). No layer before move, see layer after move. + fill_render(rgba_green); + sampleArea.offsetTo(600, 600); + composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener); + EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_NEAR(listener->luma(), luma_gray, error_margin); + listener->reset(); + SurfaceComposerClient::Transaction{}.setPosition(mContentLayer, 600, 600).apply(); + EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received"; + EXPECT_NEAR(listener->luma(), luma_green, error_margin); + composer->removeRegionSamplingListener(listener); +} + } // namespace android::test diff --git a/libs/input/Keyboard.cpp b/libs/input/Keyboard.cpp index 0c22bfefed..56900c129e 100644 --- a/libs/input/Keyboard.cpp +++ b/libs/input/Keyboard.cpp @@ -38,29 +38,29 @@ KeyMap::KeyMap() { KeyMap::~KeyMap() { } -status_t KeyMap::load(const InputDeviceIdentifier& deviceIdenfifier, +status_t KeyMap::load(const InputDeviceIdentifier& deviceIdentifier, const PropertyMap* deviceConfiguration) { // Use the configured key layout if available. if (deviceConfiguration) { String8 keyLayoutName; if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"), keyLayoutName)) { - status_t status = loadKeyLayout(deviceIdenfifier, keyLayoutName.c_str()); + status_t status = loadKeyLayout(deviceIdentifier, keyLayoutName.c_str()); if (status == NAME_NOT_FOUND) { ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but " "it was not found.", - deviceIdenfifier.name.c_str(), keyLayoutName.string()); + deviceIdentifier.name.c_str(), keyLayoutName.string()); } } String8 keyCharacterMapName; if (deviceConfiguration->tryGetProperty(String8("keyboard.characterMap"), keyCharacterMapName)) { - status_t status = loadKeyCharacterMap(deviceIdenfifier, keyCharacterMapName.c_str()); + status_t status = loadKeyCharacterMap(deviceIdentifier, keyCharacterMapName.c_str()); if (status == NAME_NOT_FOUND) { ALOGE("Configuration for keyboard device '%s' requested keyboard character " "map '%s' but it was not found.", - deviceIdenfifier.name.c_str(), keyLayoutName.string()); + deviceIdentifier.name.c_str(), keyCharacterMapName.string()); } } @@ -70,25 +70,25 @@ status_t KeyMap::load(const InputDeviceIdentifier& deviceIdenfifier, } // Try searching by device identifier. - if (probeKeyMap(deviceIdenfifier, "")) { + if (probeKeyMap(deviceIdentifier, "")) { return OK; } // Fall back on the Generic key map. // TODO Apply some additional heuristics here to figure out what kind of // generic key map to use (US English, etc.) for typical external keyboards. - if (probeKeyMap(deviceIdenfifier, "Generic")) { + if (probeKeyMap(deviceIdentifier, "Generic")) { return OK; } // Try the Virtual key map as a last resort. - if (probeKeyMap(deviceIdenfifier, "Virtual")) { + if (probeKeyMap(deviceIdentifier, "Virtual")) { return OK; } // Give up! ALOGE("Could not determine key map for device '%s' and no default key maps were found!", - deviceIdenfifier.name.c_str()); + deviceIdentifier.name.c_str()); return NAME_NOT_FOUND; } diff --git a/libs/vr/libbufferhub/consumer_buffer.cpp b/libs/vr/libbufferhub/consumer_buffer.cpp index 115e8666e5..7823e36d3d 100644 --- a/libs/vr/libbufferhub/consumer_buffer.cpp +++ b/libs/vr/libbufferhub/consumer_buffer.cpp @@ -52,12 +52,6 @@ int ConsumerBuffer::LocalAcquire(DvrNativeBufferMetadata* out_meta, while (!buffer_state_->compare_exchange_weak( current_buffer_state, updated_buffer_state, std::memory_order_acq_rel, std::memory_order_acquire)) { - ALOGD( - "%s Failed to acquire the buffer. Current buffer state was changed to " - "%" PRIx32 - " when trying to acquire the buffer and modify the buffer state to " - "%" PRIx32 ". About to try again if the buffer is still posted.", - __FUNCTION__, current_buffer_state, updated_buffer_state); if (!BufferHubDefs::isClientPosted(current_buffer_state, client_state_mask())) { ALOGE( @@ -152,12 +146,6 @@ int ConsumerBuffer::LocalRelease(const DvrNativeBufferMetadata* meta, while (!buffer_state_->compare_exchange_weak( current_buffer_state, updated_buffer_state, std::memory_order_acq_rel, std::memory_order_acquire)) { - ALOGD( - "%s: Failed to release the buffer. Current buffer state was changed to " - "%" PRIx32 - " when trying to release the buffer and modify the buffer state to " - "%" PRIx32 ". About to try again.", - __FUNCTION__, current_buffer_state, updated_buffer_state); // The failure of compare_exchange_weak updates current_buffer_state. updated_buffer_state = current_buffer_state & (~client_state_mask()); } diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp index 3d88ba5dbe..aa9d07282b 100644 --- a/libs/vr/libbufferhub/producer_buffer.cpp +++ b/libs/vr/libbufferhub/producer_buffer.cpp @@ -96,13 +96,6 @@ int ProducerBuffer::LocalPost(const DvrNativeBufferMetadata* meta, while (!buffer_state_->compare_exchange_weak( current_buffer_state, updated_buffer_state, std::memory_order_acq_rel, std::memory_order_acquire)) { - ALOGD( - "%s: Failed to post the buffer. Current buffer state was changed to " - "%" PRIx32 - " when trying to post the buffer and modify the buffer state to " - "%" PRIx32 - ". About to try again if the buffer is still gained by this client.", - __FUNCTION__, current_buffer_state, updated_buffer_state); if (!BufferHubDefs::isClientGained(current_buffer_state, client_state_mask())) { ALOGE( @@ -186,15 +179,6 @@ int ProducerBuffer::LocalGain(DvrNativeBufferMetadata* out_meta, while (!buffer_state_->compare_exchange_weak( current_buffer_state, updated_buffer_state, std::memory_order_acq_rel, std::memory_order_acquire)) { - ALOGD( - "%s: Failed to gain the buffer. Current buffer state was changed to " - "%" PRIx32 - " when trying to gain the buffer and modify the buffer state to " - "%" PRIx32 - ". About to try again if the buffer is still not read by other " - "clients.", - __FUNCTION__, current_buffer_state, updated_buffer_state); - if (BufferHubDefs::isAnyClientAcquired(current_buffer_state) || BufferHubDefs::isAnyClientGained(current_buffer_state) || (BufferHubDefs::isAnyClientPosted( diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp index abc7a72716..8144c8a7c5 100644 --- a/opengl/libs/Android.bp +++ b/opengl/libs/Android.bp @@ -162,7 +162,7 @@ cc_library_shared { "libEGL_getProcAddress", "libEGL_blobCache", ], - ldflags: ["-Wl,--exclude-libs=ALL"], + ldflags: ["-Wl,--exclude-libs=ALL,--Bsymbolic-functions"], export_include_dirs: ["EGL/include"], } diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp index ce5627271a..af023148cc 100644 --- a/services/inputflinger/EventHub.cpp +++ b/services/inputflinger/EventHub.cpp @@ -28,7 +28,6 @@ #include <sys/limits.h> #include <sys/inotify.h> #include <sys/ioctl.h> -#include <sys/utsname.h> #include <unistd.h> #define LOG_TAG "EventHub" @@ -94,14 +93,6 @@ static std::string sha1(const std::string& in) { return out; } -static void getLinuxRelease(int* major, int* minor) { - struct utsname info; - if (uname(&info) || sscanf(info.release, "%d.%d", major, minor) <= 0) { - *major = 0, *minor = 0; - ALOGE("Could not get linux version: %s", strerror(errno)); - } -} - /** * Return true if name matches "v4l-touch*" */ @@ -292,11 +283,6 @@ EventHub::EventHub(void) : result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem); LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d", errno); - - int major, minor; - getLinuxRelease(&major, &minor); - // EPOLLWAKEUP was introduced in kernel 3.5 - mUsingEpollWakeup = major > 3 || (major == 3 && minor >= 5); } EventHub::~EventHub(void) { @@ -1487,28 +1473,13 @@ void EventHub::configureFd(Device* device) { } } - std::string wakeMechanism = "EPOLLWAKEUP"; - if (!mUsingEpollWakeup) { -#ifndef EVIOCSSUSPENDBLOCK - // uapi headers don't include EVIOCSSUSPENDBLOCK, and future kernels - // will use an epoll flag instead, so as long as we want to support - // this feature, we need to be prepared to define the ioctl ourselves. -#define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int) -#endif - if (ioctl(device->fd, EVIOCSSUSPENDBLOCK, 1)) { - wakeMechanism = "<none>"; - } else { - wakeMechanism = "EVIOCSSUSPENDBLOCK"; - } - } // Tell the kernel that we want to use the monotonic clock for reporting timestamps // associated with input events. This is important because the input system // uses the timestamps extensively and assumes they were recorded using the monotonic // clock. int clockId = CLOCK_MONOTONIC; bool usingClockIoctl = !ioctl(device->fd, EVIOCSCLOCKID, &clockId); - ALOGI("wakeMechanism=%s, usingClockIoctl=%s", wakeMechanism.c_str(), - toString(usingClockIoctl)); + ALOGI("usingClockIoctl=%s", toString(usingClockIoctl)); } void EventHub::openVideoDeviceLocked(const std::string& devicePath) { diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h index 63a20ef3e2..eb4e8f2e50 100644 --- a/services/inputflinger/EventHub.h +++ b/services/inputflinger/EventHub.h @@ -479,8 +479,6 @@ private: size_t mPendingEventCount; size_t mPendingEventIndex; bool mPendingINotify; - - bool mUsingEpollWakeup; }; }; // namespace android diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 5b298b4a93..6e953f4af6 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -149,7 +149,7 @@ filegroup { "Scheduler/DispSyncSource.cpp", "Scheduler/EventControlThread.cpp", "Scheduler/EventThread.cpp", - "Scheduler/IdleTimer.cpp", + "Scheduler/OneShotTimer.cpp", "Scheduler/LayerHistory.cpp", "Scheduler/LayerInfo.cpp", "Scheduler/MessageQueue.cpp", diff --git a/services/surfaceflinger/CompositionEngine/tests/FloatRectMatcher.h b/services/surfaceflinger/CompositionEngine/tests/FloatRectMatcher.h new file mode 100644 index 0000000000..6741cc9b7a --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/tests/FloatRectMatcher.h @@ -0,0 +1,48 @@ +/* + * Copyright 2019 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. + */ + +#pragma once + +#include <string> + +#include <android-base/stringprintf.h> +#include <gmock/gmock.h> + +namespace { + +using android::base::StringAppendF; +using FloatRect = android::FloatRect; + +void dumpFloatRect(const FloatRect& rect, std::string& result, const char* name) { + StringAppendF(&result, "%s (%f %f %f %f) ", name, rect.left, rect.top, rect.right, rect.bottom); +} + +// Checks for a region match +MATCHER_P(FloatRectEq, expected, "") { + std::string buf; + buf.append("FloatRects are not equal\n"); + dumpFloatRect(expected, buf, "expected rect"); + dumpFloatRect(arg, buf, "actual rect"); + *result_listener << buf; + + const float TOLERANCE = 1e-3f; + return (std::fabs(expected.left - arg.left) < TOLERANCE) && + (std::fabs(expected.top - arg.top) < TOLERANCE) && + (std::fabs(expected.right - arg.right) < TOLERANCE) && + (std::fabs(expected.bottom - arg.bottom) < TOLERANCE); +} + +} // namespace diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index 2060c5aaff..ae906cd525 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -21,6 +21,7 @@ #include <compositionengine/mock/Output.h> #include <gtest/gtest.h> +#include "FloatRectMatcher.h" #include "MockHWC2.h" #include "MockHWComposer.h" #include "RectMatcher.h" @@ -106,6 +107,114 @@ TEST_F(OutputLayerTest, initializingOutputLayerWithHwcDisplayCreatesHwcLayer) { } /* + * OutputLayer::calculateOutputSourceCrop() + */ + +struct OutputLayerSourceCropTest : public OutputLayerTest { + OutputLayerSourceCropTest() { + // Set reasonable default values for a simple case. Each test will + // set one specific value to something different. + mLayerState.frontEnd.geomUsesSourceCrop = true; + mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 1920, 1080}; + mLayerState.frontEnd.geomActiveTransparentRegion = Region{}; + mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f}; + mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT}; + mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080}; + mLayerState.frontEnd.geomBufferTransform = TR_IDENT; + + mOutputState.viewport = Rect{0, 0, 1920, 1080}; + } + + FloatRect calculateOutputSourceCrop() { + mLayerState.frontEnd.geomInverseLayerTransform = + mLayerState.frontEnd.geomLayerTransform.inverse(); + + return mOutputLayer.calculateOutputSourceCrop(); + } +}; + +TEST_F(OutputLayerSourceCropTest, computesEmptyIfSourceCropNotUsed) { + mLayerState.frontEnd.geomUsesSourceCrop = false; + + const FloatRect expected{}; + EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); +} + +TEST_F(OutputLayerSourceCropTest, correctForSimpleDefaultCase) { + const FloatRect expected{0.f, 0.f, 1920.f, 1080.f}; + EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); +} + +TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewport) { + mLayerState.frontEnd.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f}; + + const FloatRect expected{0.f, 0.f, 1920.f, 1080.f}; + EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); +} + +TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewportRotated) { + mLayerState.frontEnd.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f}; + mLayerState.frontEnd.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080); + + const FloatRect expected{0.f, 0.f, 1080.f, 1080.f}; + EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); +} + +TEST_F(OutputLayerSourceCropTest, calculateOutputSourceCropWorksWithATransformedBuffer) { + struct Entry { + uint32_t bufferInvDisplay; + uint32_t buffer; + uint32_t display; + FloatRect expected; + }; + // Not an exhaustive list of cases, but hopefully enough. + const std::array<Entry, 12> testData = { + // clang-format off + // inv buffer display expected + /* 0 */ Entry{false, TR_IDENT, TR_IDENT, FloatRect{0.f, 0.f, 1920.f, 1080.f}}, + /* 1 */ Entry{false, TR_IDENT, TR_ROT_90, FloatRect{0.f, 0.f, 1920.f, 1080.f}}, + /* 2 */ Entry{false, TR_IDENT, TR_ROT_180, FloatRect{0.f, 0.f, 1920.f, 1080.f}}, + /* 3 */ Entry{false, TR_IDENT, TR_ROT_270, FloatRect{0.f, 0.f, 1920.f, 1080.f}}, + + /* 4 */ Entry{true, TR_IDENT, TR_IDENT, FloatRect{0.f, 0.f, 1920.f, 1080.f}}, + /* 5 */ Entry{true, TR_IDENT, TR_ROT_90, FloatRect{0.f, 0.f, 1920.f, 1080.f}}, + /* 6 */ Entry{true, TR_IDENT, TR_ROT_180, FloatRect{0.f, 0.f, 1920.f, 1080.f}}, + /* 7 */ Entry{true, TR_IDENT, TR_ROT_270, FloatRect{0.f, 0.f, 1920.f, 1080.f}}, + + /* 8 */ Entry{false, TR_IDENT, TR_IDENT, FloatRect{0.f, 0.f, 1920.f, 1080.f}}, + /* 9 */ Entry{false, TR_ROT_90, TR_ROT_90, FloatRect{0.f, 0.f, 1920.f, 1080.f}}, + /* 10 */ Entry{false, TR_ROT_180, TR_ROT_180, FloatRect{0.f, 0.f, 1920.f, 1080.f}}, + /* 11 */ Entry{false, TR_ROT_270, TR_ROT_270, FloatRect{0.f, 0.f, 1920.f, 1080.f}}, + + // clang-format on + }; + + for (size_t i = 0; i < testData.size(); i++) { + const auto& entry = testData[i]; + + mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = entry.bufferInvDisplay; + mLayerState.frontEnd.geomBufferTransform = entry.buffer; + mOutputState.orientation = entry.display; + + EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(entry.expected)) << "entry " << i; + } +} + +TEST_F(OutputLayerSourceCropTest, geomContentCropAffectsCrop) { + mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 960, 540}; + + const FloatRect expected{0.f, 0.f, 960.f, 540.f}; + EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); +} + +TEST_F(OutputLayerSourceCropTest, viewportAffectsCrop) { + mOutputState.viewport = Rect{0, 0, 960, 540}; + + const FloatRect expected{0.f, 0.f, 960.f, 540.f}; + EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); +} + +/* * OutputLayer::calculateOutputDisplayFrame() */ @@ -163,7 +272,7 @@ TEST_F(OutputLayerDisplayFrameTest, emptyGeomCropIsNotUsedToComputeFrame) { EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); } -TEST_F(OutputLayerDisplayFrameTest, geomLayerSnapToBoundsAffectsFrame) { +TEST_F(OutputLayerDisplayFrameTest, geomLayerBoundsAffectsFrame) { mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 960.f, 540.f}; const Rect expected{0, 0, 960, 540}; EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); @@ -242,6 +351,159 @@ TEST_F(OutputLayerTest, calculateOutputRelativeBufferTransformTestsNeeded) { } } +TEST_F(OutputLayerTest, + calculateOutputRelativeBufferTransformTestWithOfBufferUsesDisplayInverseTransform) { + mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = true; + + struct Entry { + uint32_t layer; + uint32_t buffer; + uint32_t display; + uint32_t expected; + }; + // Not an exhaustive list of cases, but hopefully enough. + const std::array<Entry, 24> testData = { + // clang-format off + // layer buffer display expected + /* 0 */ Entry{TR_IDENT, TR_IDENT, TR_IDENT, TR_IDENT}, + /* 1 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_90, TR_IDENT}, + /* 2 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_180, TR_IDENT}, + /* 3 */ Entry{TR_IDENT, TR_IDENT, TR_ROT_270, TR_IDENT}, + + /* 4 */ Entry{TR_IDENT, TR_FLP_H, TR_IDENT, TR_FLP_H}, + /* 5 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_90, TR_FLP_H}, + /* 6 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_180, TR_FLP_H}, + /* 7 */ Entry{TR_IDENT, TR_FLP_H, TR_ROT_270, TR_FLP_H}, + + /* 8 */ Entry{TR_IDENT, TR_FLP_V, TR_IDENT, TR_FLP_V}, + /* 9 */ Entry{TR_IDENT, TR_ROT_90, TR_ROT_90, TR_ROT_90}, + /* 10 */ Entry{TR_IDENT, TR_ROT_180, TR_ROT_180, TR_ROT_180}, + /* 11 */ Entry{TR_IDENT, TR_ROT_270, TR_ROT_270, TR_ROT_270}, + + /* 12 */ Entry{TR_ROT_90, TR_IDENT, TR_IDENT, TR_IDENT}, + /* 13 */ Entry{TR_ROT_90, TR_FLP_H, TR_ROT_90, TR_FLP_H}, + /* 14 */ Entry{TR_ROT_90, TR_IDENT, TR_ROT_180, TR_IDENT}, + /* 15 */ Entry{TR_ROT_90, TR_FLP_H, TR_ROT_270, TR_FLP_H}, + + /* 16 */ Entry{TR_ROT_180, TR_FLP_H, TR_IDENT, TR_FLP_H}, + /* 17 */ Entry{TR_ROT_180, TR_IDENT, TR_ROT_90, TR_IDENT}, + /* 18 */ Entry{TR_ROT_180, TR_FLP_H, TR_ROT_180, TR_FLP_H}, + /* 19 */ Entry{TR_ROT_180, TR_IDENT, TR_ROT_270, TR_IDENT}, + + /* 20 */ Entry{TR_ROT_270, TR_IDENT, TR_IDENT, TR_IDENT}, + /* 21 */ Entry{TR_ROT_270, TR_FLP_H, TR_ROT_90, TR_FLP_H}, + /* 22 */ Entry{TR_ROT_270, TR_FLP_H, TR_ROT_180, TR_FLP_H}, + /* 23 */ Entry{TR_ROT_270, TR_IDENT, TR_ROT_270, TR_IDENT}, + // clang-format on + }; + + for (size_t i = 0; i < testData.size(); i++) { + const auto& entry = testData[i]; + + mLayerState.frontEnd.geomLayerTransform = ui::Transform{entry.layer}; + mLayerState.frontEnd.geomBufferTransform = entry.buffer; + mOutputState.orientation = entry.display; + + auto actual = mOutputLayer.calculateOutputRelativeBufferTransform(); + EXPECT_EQ(entry.expected, actual) << "entry " << i; + } +} + +/* + * OutputLayer::updateCompositionState() + */ + +struct OutputLayerPartialMockForUpdateCompositionState : public impl::OutputLayer { + OutputLayerPartialMockForUpdateCompositionState(const compositionengine::Output& output, + std::shared_ptr<compositionengine::Layer> layer, + sp<compositionengine::LayerFE> layerFE) + : impl::OutputLayer(output, layer, layerFE) {} + // Mock everything called by updateCompositionState to simplify testing it. + MOCK_CONST_METHOD0(calculateOutputSourceCrop, FloatRect()); + MOCK_CONST_METHOD0(calculateOutputDisplayFrame, Rect()); + MOCK_CONST_METHOD0(calculateOutputRelativeBufferTransform, uint32_t()); +}; + +struct OutputLayerUpdateCompositionStateTest : public OutputLayerTest { +public: + OutputLayerUpdateCompositionStateTest() { + EXPECT_CALL(*mLayer, getState()).WillRepeatedly(ReturnRef(mLayerState)); + EXPECT_CALL(mOutput, getState()).WillRepeatedly(ReturnRef(mOutputState)); + } + + ~OutputLayerUpdateCompositionStateTest() = default; + + void setupGeometryChildCallValues() { + EXPECT_CALL(mOutputLayer, calculateOutputSourceCrop()).WillOnce(Return(kSourceCrop)); + EXPECT_CALL(mOutputLayer, calculateOutputDisplayFrame()).WillOnce(Return(kDisplayFrame)); + EXPECT_CALL(mOutputLayer, calculateOutputRelativeBufferTransform()) + .WillOnce(Return(mBufferTransform)); + } + + void validateComputedGeometryState() { + const auto& state = mOutputLayer.getState(); + EXPECT_EQ(kSourceCrop, state.sourceCrop); + EXPECT_EQ(kDisplayFrame, state.displayFrame); + EXPECT_EQ(static_cast<Hwc2::Transform>(mBufferTransform), state.bufferTransform); + } + + const FloatRect kSourceCrop{1.f, 2.f, 3.f, 4.f}; + const Rect kDisplayFrame{11, 12, 13, 14}; + uint32_t mBufferTransform{21}; + + using OutputLayer = OutputLayerPartialMockForUpdateCompositionState; + StrictMock<OutputLayer> mOutputLayer{mOutput, mLayer, mLayerFE}; +}; + +TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) { + mLayerState.frontEnd.isSecure = true; + mOutputState.isSecure = true; + + setupGeometryChildCallValues(); + + mOutputLayer.updateCompositionState(true); + + validateComputedGeometryState(); + + EXPECT_EQ(false, mOutputLayer.getState().forceClientComposition); +} + +TEST_F(OutputLayerUpdateCompositionStateTest, + alsoSetsForceCompositionIfSecureLayerOnNonsecureOutput) { + mLayerState.frontEnd.isSecure = true; + mOutputState.isSecure = false; + + setupGeometryChildCallValues(); + + mOutputLayer.updateCompositionState(true); + + validateComputedGeometryState(); + + EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition); +} + +TEST_F(OutputLayerUpdateCompositionStateTest, + alsoSetsForceCompositionIfUnsupportedBufferTransform) { + mLayerState.frontEnd.isSecure = true; + mOutputState.isSecure = true; + + mBufferTransform = ui::Transform::ROT_INVALID; + + setupGeometryChildCallValues(); + + mOutputLayer.updateCompositionState(true); + + validateComputedGeometryState(); + + EXPECT_EQ(true, mOutputLayer.getState().forceClientComposition); +} + +TEST_F(OutputLayerUpdateCompositionStateTest, doesNotRecomputeGeometryIfNotRequested) { + mOutputLayer.updateCompositionState(false); + + EXPECT_EQ(false, mOutputLayer.getState().forceClientComposition); +} + /* * OutputLayer::writeStateToHWC() */ diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index bda7e4308f..b2df91d4ea 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -430,7 +430,7 @@ void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositio auto& parentState = parent->getDrawingState(); const int parentType = parentState.metadata.getInt32(METADATA_WINDOW_TYPE, 0); const int parentAppId = parentState.metadata.getInt32(METADATA_OWNER_UID, 0); - if (parentType >= 0 || parentAppId >= 0) { + if (parentType > 0 && parentAppId > 0) { type = parentType; appId = parentAppId; } diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h index 3c6fcf3872..ac7339c42a 100644 --- a/services/surfaceflinger/RegionSamplingThread.h +++ b/services/surfaceflinger/RegionSamplingThread.h @@ -27,7 +27,7 @@ #include <ui/GraphicBuffer.h> #include <ui/Rect.h> #include <utils/StrongPointer.h> -#include "Scheduler/IdleTimer.h" +#include "Scheduler/OneShotTimer.h" namespace android { @@ -107,7 +107,7 @@ private: SurfaceFlinger& mFlinger; Scheduler& mScheduler; const TimingTunables mTunables; - scheduler::IdleTimer mIdleTimer; + scheduler::OneShotTimer mIdleTimer; std::unique_ptr<SamplingOffsetCallback> const mPhaseCallback; diff --git a/services/surfaceflinger/Scheduler/IdleTimer.cpp b/services/surfaceflinger/Scheduler/OneShotTimer.cpp index 37fdfc7c62..4870a3bbdd 100644 --- a/services/surfaceflinger/Scheduler/IdleTimer.cpp +++ b/services/surfaceflinger/Scheduler/OneShotTimer.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "IdleTimer.h" +#include "OneShotTimer.h" #include <chrono> #include <thread> @@ -22,23 +22,23 @@ namespace android { namespace scheduler { -IdleTimer::IdleTimer(const Interval& interval, const ResetCallback& resetCallback, - const TimeoutCallback& timeoutCallback) +OneShotTimer::OneShotTimer(const Interval& interval, const ResetCallback& resetCallback, + const TimeoutCallback& timeoutCallback) : mInterval(interval), mResetCallback(resetCallback), mTimeoutCallback(timeoutCallback) {} -IdleTimer::~IdleTimer() { +OneShotTimer::~OneShotTimer() { stop(); } -void IdleTimer::start() { +void OneShotTimer::start() { { std::lock_guard<std::mutex> lock(mMutex); mState = TimerState::RESET; } - mThread = std::thread(&IdleTimer::loop, this); + mThread = std::thread(&OneShotTimer::loop, this); } -void IdleTimer::stop() { +void OneShotTimer::stop() { { std::lock_guard<std::mutex> lock(mMutex); mState = TimerState::STOPPED; @@ -49,7 +49,7 @@ void IdleTimer::stop() { } } -void IdleTimer::loop() { +void OneShotTimer::loop() { while (true) { bool triggerReset = false; bool triggerTimeout = false; @@ -100,7 +100,7 @@ void IdleTimer::loop() { } } // namespace scheduler -void IdleTimer::reset() { +void OneShotTimer::reset() { { std::lock_guard<std::mutex> lock(mMutex); mState = TimerState::RESET; diff --git a/services/surfaceflinger/Scheduler/IdleTimer.h b/services/surfaceflinger/Scheduler/OneShotTimer.h index 2646688860..fd1aa02226 100644 --- a/services/surfaceflinger/Scheduler/IdleTimer.h +++ b/services/surfaceflinger/Scheduler/OneShotTimer.h @@ -29,15 +29,15 @@ namespace scheduler { * Class that sets off a timer for a given interval, and fires a callback when the * interval expires. */ -class IdleTimer { +class OneShotTimer { public: using Interval = std::chrono::milliseconds; using ResetCallback = std::function<void()>; using TimeoutCallback = std::function<void()>; - IdleTimer(const Interval& interval, const ResetCallback& resetCallback, - const TimeoutCallback& timeoutCallback); - ~IdleTimer(); + OneShotTimer(const Interval& interval, const ResetCallback& resetCallback, + const TimeoutCallback& timeoutCallback); + ~OneShotTimer(); // Initializes and turns on the idle timer. void start(); diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index bb24f73834..e393f1b2a6 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -38,9 +38,9 @@ #include "DispSyncSource.h" #include "EventControlThread.h" #include "EventThread.h" -#include "IdleTimer.h" #include "InjectVSyncSource.h" #include "LayerInfo.h" +#include "OneShotTimer.h" #include "SchedulerUtils.h" #include "SurfaceFlingerProperties.h" @@ -86,34 +86,29 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function, if (mSetIdleTimerMs > 0) { if (mSupportKernelTimer) { - mIdleTimer = - std::make_unique<scheduler::IdleTimer>(std::chrono::milliseconds( - mSetIdleTimerMs), - [this] { resetKernelTimerCallback(); }, - [this] { - expiredKernelTimerCallback(); - }); + mIdleTimer = std::make_unique<scheduler::OneShotTimer>( + std::chrono::milliseconds(mSetIdleTimerMs), + [this] { resetKernelTimerCallback(); }, + [this] { expiredKernelTimerCallback(); }); } else { - mIdleTimer = std::make_unique<scheduler::IdleTimer>(std::chrono::milliseconds( - mSetIdleTimerMs), - [this] { resetTimerCallback(); }, - [this] { expiredTimerCallback(); }); + mIdleTimer = std::make_unique<scheduler::OneShotTimer>( + std::chrono::milliseconds(mSetIdleTimerMs), [this] { resetTimerCallback(); }, + [this] { expiredTimerCallback(); }); } mIdleTimer->start(); } if (mSetTouchTimerMs > 0) { // Touch events are coming to SF every 100ms, so the timer needs to be higher than that - mTouchTimer = - std::make_unique<scheduler::IdleTimer>(std::chrono::milliseconds(mSetTouchTimerMs), - [this] { resetTouchTimerCallback(); }, - [this] { expiredTouchTimerCallback(); }); + mTouchTimer = std::make_unique<scheduler::OneShotTimer>( + std::chrono::milliseconds(mSetTouchTimerMs), [this] { resetTouchTimerCallback(); }, + [this] { expiredTouchTimerCallback(); }); mTouchTimer->start(); } } Scheduler::~Scheduler() { - // Ensure the IdleTimer thread is joined before we start destroying state. + // Ensure the OneShotTimer threads are joined before we start destroying state. mTouchTimer.reset(); mIdleTimer.reset(); } diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index eaad37c3ee..a30776059f 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -26,9 +26,9 @@ #include "DispSync.h" #include "EventControlThread.h" #include "EventThread.h" -#include "IdleTimer.h" #include "InjectVSyncSource.h" #include "LayerHistory.h" +#include "OneShotTimer.h" #include "RefreshRateConfigs.h" #include "SchedulerUtils.h" @@ -273,14 +273,14 @@ private: // Timer that records time between requests for next vsync. If the time is higher than a given // interval, a callback is fired. Set this variable to >0 to use this feature. int64_t mSetIdleTimerMs = 0; - std::unique_ptr<scheduler::IdleTimer> mIdleTimer; + std::unique_ptr<scheduler::OneShotTimer> mIdleTimer; // Enables whether to use idle timer callbacks that support the kernel // timer. bool mSupportKernelTimer; // Timer used to monitor touch events. int64_t mSetTouchTimerMs = 0; - std::unique_ptr<scheduler::IdleTimer> mTouchTimer; + std::unique_ptr<scheduler::OneShotTimer> mTouchTimer; std::mutex mCallbackLock; ChangeRefreshRateCallback mChangeRefreshRateCallback GUARDED_BY(mCallbackLock); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 459cd0af89..e5896f9985 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1801,6 +1801,12 @@ void SurfaceFlinger::handleMessageRefresh() { mVsyncModulator.onRefreshed(mHadClientComposition); mLayersWithQueuedFrames.clear(); + if (mVisibleRegionsDirty) { + mVisibleRegionsDirty = false; + if (mTracingEnabled) { + mTracing.notify("visibleRegionsDirty"); + } + } } @@ -1810,9 +1816,6 @@ bool SurfaceFlinger::handleMessageInvalidate() { if (mVisibleRegionsDirty) { computeLayerBounds(); - if (mTracingEnabled) { - mTracing.notify("visibleRegionsDirty"); - } } for (auto& layer : mLayersPendingRefresh) { @@ -2214,7 +2217,6 @@ void SurfaceFlinger::rebuildLayerStacks() { // rebuild the visible layer list per screen if (CC_UNLIKELY(mVisibleRegionsDirty)) { ATRACE_NAME("rebuildLayerStacks VR Dirty"); - mVisibleRegionsDirty = false; invalidateHwcGeometry(); for (const auto& pair : mDisplays) { @@ -3931,6 +3933,11 @@ uint32_t SurfaceFlinger::setClientStateLocked( sp<Layer> layer(client->getLayerUser(s.surface)); if (layer == nullptr) { + for (auto& listenerCallback : listenerCallbacks) { + mTransactionCompletedThread.addUnpresentedCallbackHandle( + new CallbackHandle(listenerCallback.transactionCompletedListener, + listenerCallback.callbackIds, s.surface)); + } return 0; } diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop index decabd5e88..a8ec7649c6 100644 --- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop +++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop @@ -36,7 +36,7 @@ owner: Platform prop { api_name: "vsync_event_phase_offset_ns" type: Long - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.vsync_event_phase_offset_ns" } @@ -44,7 +44,7 @@ prop { prop { api_name: "vsync_sf_event_phase_offset_ns" type: Long - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.vsync_sf_event_phase_offset_ns" } @@ -53,7 +53,7 @@ prop { prop { api_name: "use_context_priority" type: Boolean - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.use_context_priority" } @@ -62,7 +62,7 @@ prop { prop { api_name: "max_frame_buffer_acquired_buffers" type: Long - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.max_frame_buffer_acquired_buffers" } @@ -80,7 +80,7 @@ prop { prop { api_name: "has_wide_color_display" type: Boolean - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.has_wide_color_display" } @@ -90,7 +90,7 @@ prop { prop { api_name: "running_without_sync_framework" type: Boolean - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.running_without_sync_framework" } @@ -108,7 +108,7 @@ prop { prop { api_name: "has_HDR_display" type: Boolean - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.has_HDR_display" } @@ -117,7 +117,7 @@ prop { prop { api_name: "present_time_offset_from_vsync_ns" type: Long - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.present_time_offset_from_vsync_ns" } @@ -129,7 +129,7 @@ prop { prop { api_name: "force_hwc_copy_for_virtual_displays" type: Boolean - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.force_hwc_copy_for_virtual_displays" } @@ -139,7 +139,7 @@ prop { prop { api_name: "max_virtual_display_dimension" type: Long - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.max_virtual_display_dimension" } @@ -151,7 +151,7 @@ prop { prop { api_name: "use_vr_flinger" type: Boolean - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.use_vr_flinger" } @@ -161,7 +161,7 @@ prop { prop { api_name: "start_graphics_allocator_service" type: Boolean - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.start_graphics_allocator_service" } @@ -171,7 +171,7 @@ prop { api_name: "primary_display_orientation" type: Enum enum_values: "ORIENTATION_0|ORIENTATION_90|ORIENTATION_180|ORIENTATION_270" - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.primary_display_orientation" } @@ -182,7 +182,7 @@ prop { prop { api_name: "use_color_management" type: Boolean - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.use_color_management" } @@ -209,7 +209,7 @@ prop { prop { api_name: "default_composition_dataspace" type: Long - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.default_composition_dataspace" } @@ -220,7 +220,7 @@ prop { prop { api_name: "default_composition_pixel_format" type: Integer - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.default_composition_pixel_format" } @@ -235,7 +235,7 @@ prop { prop { api_name: "wcg_composition_dataspace" type: Long - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.wcg_composition_dataspace" } @@ -246,7 +246,7 @@ prop { prop { api_name: "wcg_composition_pixel_format" type: Integer - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.wcg_composition_pixel_format" } @@ -258,7 +258,7 @@ prop { prop { api_name: "display_primary_red" type: DoubleList - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.display_primary_red" } @@ -266,7 +266,7 @@ prop { prop { api_name: "display_primary_green" type: DoubleList - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.display_primary_green" } @@ -274,7 +274,7 @@ prop { prop { api_name: "display_primary_blue" type: DoubleList - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.display_primary_blue" } @@ -282,7 +282,7 @@ prop { prop { api_name: "display_primary_white" type: DoubleList - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.display_primary_white" } @@ -293,7 +293,7 @@ prop { prop { api_name: "set_idle_timer_ms" type: Integer - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.set_idle_timer_ms" } @@ -304,7 +304,7 @@ prop { prop { api_name: "set_touch_timer_ms" type: Integer - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.set_touch_timer_ms" } @@ -314,7 +314,7 @@ prop { prop { api_name: "use_smart_90_for_video" type: Boolean - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.use_smart_90_for_video" } @@ -322,7 +322,7 @@ prop { prop { api_name: "enable_protected_contents" type: Boolean - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.protected_contents" } @@ -332,7 +332,7 @@ prop { prop { api_name: "support_kernel_idle_timer" type: Boolean - scope: System + scope: Public access: Readonly prop_name: "ro.surface_flinger.support_kernel_idle_timer" } diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index f842d61c7f..4917bc2a51 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -42,7 +42,7 @@ cc_test { "DisplayTransactionTest.cpp", "EventControlThreadTest.cpp", "EventThreadTest.cpp", - "IdleTimerTest.cpp", + "OneShotTimerTest.cpp", "LayerHistoryTest.cpp", "LayerMetadataTest.cpp", "SchedulerTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/IdleTimerTest.cpp b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp index eff22b6640..0208728026 100644 --- a/services/surfaceflinger/tests/unittests/IdleTimerTest.cpp +++ b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp @@ -21,17 +21,17 @@ #include <utils/Log.h> #include "AsyncCallRecorder.h" -#include "Scheduler/IdleTimer.h" +#include "Scheduler/OneShotTimer.h" using namespace std::chrono_literals; namespace android { namespace scheduler { -class IdleTimerTest : public testing::Test { +class OneShotTimerTest : public testing::Test { protected: - IdleTimerTest() = default; - ~IdleTimerTest() override = default; + OneShotTimerTest() = default; + ~OneShotTimerTest() override = default; // This timeout should be used when a 3ms callback is expected. // While the tests typically request a callback after 3ms, the scheduler @@ -46,7 +46,7 @@ protected: AsyncCallRecorder<void (*)()> mResetTimerCallback; AsyncCallRecorder<void (*)()> mExpiredTimerCallback; - std::unique_ptr<IdleTimer> mIdleTimer; + std::unique_ptr<OneShotTimer> mIdleTimer; void clearPendingCallbacks() { while (mExpiredTimerCallback.waitForCall(0us).has_value()) { @@ -55,13 +55,14 @@ protected: }; namespace { -TEST_F(IdleTimerTest, createAndDestroyTest) { - mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, [] {}, [] {}); +TEST_F(OneShotTimerTest, createAndDestroyTest) { + mIdleTimer = std::make_unique<scheduler::OneShotTimer>( + 3ms, [] {}, [] {}); } -TEST_F(IdleTimerTest, startStopTest) { - mIdleTimer = std::make_unique<scheduler::IdleTimer>(30ms, mResetTimerCallback.getInvocable(), - mExpiredTimerCallback.getInvocable()); +TEST_F(OneShotTimerTest, startStopTest) { + mIdleTimer = std::make_unique<scheduler::OneShotTimer>(30ms, mResetTimerCallback.getInvocable(), + mExpiredTimerCallback.getInvocable()); auto startTime = std::chrono::steady_clock::now(); mIdleTimer->start(); EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value()); @@ -70,7 +71,7 @@ TEST_F(IdleTimerTest, startStopTest) { bool callbackCalled = mExpiredTimerCallback.waitForCall(25ms).has_value(); // Under ideal conditions there should be no event. But occasionally // it is possible that the wait just prior takes more than 30ms, and - // a callback is observed. We check the elapsed time since before the IdleTimer + // a callback is observed. We check the elapsed time since before the OneShotTimer // thread was started as a sanity check to not have a flakey test. EXPECT_FALSE(callbackCalled && std::chrono::steady_clock::now() - startTime < 30ms); @@ -79,9 +80,9 @@ TEST_F(IdleTimerTest, startStopTest) { mIdleTimer->stop(); } -TEST_F(IdleTimerTest, resetTest) { - mIdleTimer = std::make_unique<scheduler::IdleTimer>(20ms, mResetTimerCallback.getInvocable(), - mExpiredTimerCallback.getInvocable()); +TEST_F(OneShotTimerTest, resetTest) { + mIdleTimer = std::make_unique<scheduler::OneShotTimer>(20ms, mResetTimerCallback.getInvocable(), + mExpiredTimerCallback.getInvocable()); mIdleTimer->start(); EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value()); // Observe any event that happens in about 25ms. We don't care if one was @@ -104,9 +105,9 @@ TEST_F(IdleTimerTest, resetTest) { EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value()); } -TEST_F(IdleTimerTest, resetBackToBackTest) { - mIdleTimer = std::make_unique<scheduler::IdleTimer>(20ms, mResetTimerCallback.getInvocable(), - mExpiredTimerCallback.getInvocable()); +TEST_F(OneShotTimerTest, resetBackToBackTest) { + mIdleTimer = std::make_unique<scheduler::OneShotTimer>(20ms, mResetTimerCallback.getInvocable(), + mExpiredTimerCallback.getInvocable()); mIdleTimer->start(); EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value()); @@ -135,9 +136,9 @@ TEST_F(IdleTimerTest, resetBackToBackTest) { EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value()); } -TEST_F(IdleTimerTest, startNotCalledTest) { - mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(), - mExpiredTimerCallback.getInvocable()); +TEST_F(OneShotTimerTest, startNotCalledTest) { + mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(), + mExpiredTimerCallback.getInvocable()); // The start hasn't happened, so the callback does not happen. EXPECT_FALSE(mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback).has_value()); EXPECT_FALSE(mResetTimerCallback.waitForCall().has_value()); @@ -147,9 +148,9 @@ TEST_F(IdleTimerTest, startNotCalledTest) { EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value()); } -TEST_F(IdleTimerTest, idleTimerIdlesTest) { - mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(), - mExpiredTimerCallback.getInvocable()); +TEST_F(OneShotTimerTest, idleTimerIdlesTest) { + mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(), + mExpiredTimerCallback.getInvocable()); mIdleTimer->start(); EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value()); @@ -167,18 +168,18 @@ TEST_F(IdleTimerTest, idleTimerIdlesTest) { EXPECT_FALSE(mResetTimerCallback.waitForCall(0ms).has_value()); } -TEST_F(IdleTimerTest, timeoutCallbackExecutionTest) { - mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(), - mExpiredTimerCallback.getInvocable()); +TEST_F(OneShotTimerTest, timeoutCallbackExecutionTest) { + mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(), + mExpiredTimerCallback.getInvocable()); mIdleTimer->start(); EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value()); EXPECT_TRUE(mExpiredTimerCallback.waitForCall(waitTimeForExpected3msCallback).has_value()); mIdleTimer->stop(); } -TEST_F(IdleTimerTest, noCallbacksAfterStopAndResetTest) { - mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(), - mExpiredTimerCallback.getInvocable()); +TEST_F(OneShotTimerTest, noCallbacksAfterStopAndResetTest) { + mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(), + mExpiredTimerCallback.getInvocable()); mIdleTimer->start(); EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value()); EXPECT_TRUE(mExpiredTimerCallback.waitForCall(waitTimeForExpected3msCallback).has_value()); @@ -190,9 +191,9 @@ TEST_F(IdleTimerTest, noCallbacksAfterStopAndResetTest) { EXPECT_FALSE(mResetTimerCallback.waitForCall().has_value()); } -TEST_F(IdleTimerTest, noCallbacksAfterStopTest) { - mIdleTimer = std::make_unique<scheduler::IdleTimer>(3ms, mResetTimerCallback.getInvocable(), - mExpiredTimerCallback.getInvocable()); +TEST_F(OneShotTimerTest, noCallbacksAfterStopTest) { + mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(), + mExpiredTimerCallback.getInvocable()); mIdleTimer->start(); EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value()); diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp index a7fd912294..b71964ba00 100644 --- a/services/vr/bufferhubd/producer_channel.cpp +++ b/services/vr/bufferhubd/producer_channel.cpp @@ -350,7 +350,7 @@ Status<RemoteChannelHandle> ProducerChannel::CreateConsumer( while (!buffer_state_->compare_exchange_weak( current_buffer_state, updated_buffer_state, std::memory_order_acq_rel, std::memory_order_acquire)) { - ALOGI( + ALOGV( "%s: Failed to post to the new consumer. " "Current buffer state was changed to %" PRIx32 " when trying to acquire the buffer and modify the buffer state to " diff --git a/services/vr/hardware_composer/impl/vr_hwc.cpp b/services/vr/hardware_composer/impl/vr_hwc.cpp index fb7932d804..7323277248 100644 --- a/services/vr/hardware_composer/impl/vr_hwc.cpp +++ b/services/vr/hardware_composer/impl/vr_hwc.cpp @@ -994,6 +994,26 @@ void VrHwc::UpdateVsyncCallbackEnabledLocked() { vsync_callback_->SetEventCallback(send_vsync ? event_callback_ : nullptr); } +Return<void> VrHwc::debug(const hidl_handle& fd, + const hidl_vec<hidl_string>& args) { + std::string result; + + { + std::lock_guard<std::mutex> guard(mutex_); + for (const auto& pair : displays_) { + result += StringPrintf("Display id: %d\n", static_cast<int>(pair.first)); + pair.second->dumpDebugInfo(&result); + } + result += "\n"; + } + + FILE* out = fdopen(dup(fd->data[0]), "w"); + fprintf(out, "%s", result.c_str()); + fclose(out); + + return Void(); +} + void HwcLayer::dumpDebugInfo(std::string* result) const { if (!result) { return; diff --git a/services/vr/hardware_composer/impl/vr_hwc.h b/services/vr/hardware_composer/impl/vr_hwc.h index e8c0212039..15358c57bb 100644 --- a/services/vr/hardware_composer/impl/vr_hwc.h +++ b/services/vr/hardware_composer/impl/vr_hwc.h @@ -295,6 +295,9 @@ class VrHwc : public IComposer, public ComposerHal, public ComposerView { void RegisterObserver(Observer* observer) override; void UnregisterObserver(Observer* observer) override; + Return<void> debug(const hidl_handle& fd, + const hidl_vec<hidl_string>& args) override; + private: class VsyncCallback : public BnVsyncCallback { public: diff --git a/services/vr/virtual_touchpad/virtual_touchpad.rc b/services/vr/virtual_touchpad/virtual_touchpad.rc index 99315ef341..0de0f9eec7 100644 --- a/services/vr/virtual_touchpad/virtual_touchpad.rc +++ b/services/vr/virtual_touchpad/virtual_touchpad.rc @@ -1,5 +1,5 @@ service virtual_touchpad /system/bin/virtual_touchpad class core user system - group system input + group system input uhid writepid /dev/cpuset/system/tasks diff --git a/vulkan/api/templates/asciidoc.tmpl b/vulkan/api/templates/asciidoc.tmpl deleted file mode 100644 index 3009e19cad..0000000000 --- a/vulkan/api/templates/asciidoc.tmpl +++ /dev/null @@ -1,151 +0,0 @@ -{{Include "vulkan_common.tmpl"}} -{{if not (Global "AsciiDocPath")}}{{Global "AsciiDocPath" "../../doc/specs/vulkan/"}}{{end}} -{{$ | Macro "AsciiDoc.Main"}} - - -{{/* -------------------------------------------------------------------------------- - AsciiDoc generation main entry point. -------------------------------------------------------------------------------- -*/}} -{{define "AsciiDoc.Main"}} - {{$docPath := Global "AsciiDocPath"}} - - {{/* Generate AsciiDoc files for API enums and bitfields (flags). */}} - {{range $e := $.Enums}} - {{if not $e.IsBitfield}} - {{$filename := print $docPath "enums/" (Macro "EnumName" $e) ".txt"}} - {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Enum" $e) "File" $filename}} - {{else}} - {{$filename := print $docPath "flags/" (Macro "EnumName" $e) ".txt"}} - {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Flag" $e) "File" $filename}} - {{end}} - {{end}} - - {{/* Generate AsciiDoc files for API commands (protos). */}} - {{range $f := (AllCommands $)}} - {{if not (GetAnnotation $f "pfn")}} - {{$filename := print $docPath "protos/" $f.Name ".txt"}} - {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Proto" $f) "File" $filename}} - {{end}} - {{end}} - - {{/* Generate AsciiDoc files for API structs. */}} - {{range $c := $.Classes}} - {{if not (GetAnnotation $c "internal")}} - {{$filename := print $docPath "structs/" $c.Name ".txt"}} - {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Struct" $c) "File" $filename}} - {{end}} - {{end}} -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits the AsciiDoc contents for the specified API enum. -------------------------------------------------------------------------------- -*/}} -{{define "AsciiDoc.Enum"}} - {{AssertType $ "Enum"}} - - {{Macro "Docs" $.Docs}} - typedef enum { - {{range $i, $e := $.Entries}} - {{Macro "EnumEntry" $e}} = {{AsSigned $e.Value}}, {{Macro "Docs" $e.Docs}} - {{end}} - ¶ - {{$name := Macro "EnumName" $ | TrimRight "ABCDEFGHIJKLMNOQRSTUVWXYZ" | SplitPascalCase | Upper | JoinWith "_"}} - {{$first := Macro "EnumFirstEntry" $}} - {{$last := Macro "EnumLastEntry" $}} - {{$name}}_BEGIN_RANGE = {{$first}}, - {{$name}}_END_RANGE = {{$last}}, - {{$name}}_NUM = ({{$last}} - {{$first}} + 1), - {{$name}}_MAX_ENUM = 0x7FFFFFFF - } {{Macro "EnumName" $}}; -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits the AsciiDoc contents for the specified API bitfield. -------------------------------------------------------------------------------- -*/}} -{{define "AsciiDoc.Flag"}} - {{AssertType $ "Enum"}} - - {{Macro "Docs" $.Docs}} - typedef VkFlags {{Macro "EnumName" $}}; - {{if $.Entries}} - typedef enum { - {{range $e := $.Entries}} - {{Macro "BitfieldEntryName" $e}} = {{printf "%#.8x" $e.Value}}, {{Macro "Docs" $e.Docs}} - {{end}} - } {{Macro "EnumName" $ | TrimRight "s"}}Bits; - {{end}} -{{end}} - - - -{{/* -------------------------------------------------------------------------------- - Emits the AsciiDoc contents for the specified API class. -------------------------------------------------------------------------------- -*/}} -{{define "AsciiDoc.Struct"}} - {{AssertType $ "Class"}} - - {{Macro "Docs" $.Docs}} - typedef {{if GetAnnotation $ "union"}}union{{else}}struct{{end}} { - {{range $f := $.Fields}} - {{Node "Type" $f}} {{$f.Name}}{{Macro "ArrayPostfix" (TypeOf $f)}}; {{Macro "Docs" $f.Docs}} - {{end}} - } {{Macro "StructName" $}}; -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits the AsciiDoc contents for the specified API function. -------------------------------------------------------------------------------- -*/}} -{{define "AsciiDoc.Proto"}} - {{AssertType $ "Function"}} - - {{Macro "Docs" $.Docs}} - {{Node "Type" $.Return}} VKAPI {{Macro "FunctionName" $}}({{Macro "Parameters" $}}); -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Wraps the specified Code in AsciiDoc source tags then writes to the specified File. -------------------------------------------------------------------------------- -*/}} -{{define "AsciiDoc.Write"}} - {{AssertType $.Code "string"}} - {{AssertType $.File "string"}} - - {{$code := $.Code | Format (Global "clang-format")}} - {{JoinWith "\n" (Macro "AsciiDoc.Header") $code (Macro "AsciiDoc.Footer") ""| Write $.File}} -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits an AsciiDoc source header. -------------------------------------------------------------------------------- -*/}} -{{define "AsciiDoc.Header"}} -[source,{basebackend@docbook:c++:cpp}] ------------------------------------------------------------------------------- -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits an AsciiDoc source footer. -------------------------------------------------------------------------------- -*/}} -{{define "AsciiDoc.Footer"}} ------------------------------------------------------------------------------- -{{end}} diff --git a/vulkan/api/templates/vk_xml.tmpl b/vulkan/api/templates/vk_xml.tmpl deleted file mode 100644 index 893bde7833..0000000000 --- a/vulkan/api/templates/vk_xml.tmpl +++ /dev/null @@ -1,435 +0,0 @@ -{{Include "vulkan_common.tmpl"}} -{{Macro "DefineGlobals" $}} -{{$ | Macro "vk.xml" | Reflow 4 | Write "vk.xml"}} - - -{{/* -------------------------------------------------------------------------------- - Entry point -------------------------------------------------------------------------------- -*/}} -{{define "vk.xml"}} -<?xml version="1.0" encoding="UTF-8"?> -<registry> - »<comment>« -Copyright (c) 2015 The Khronos Group Inc. -¶ -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and/or associated documentation files (the -"Materials"), to deal in the Materials without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Materials, and to -permit persons to whom the Materials are furnished to do so, subject to -the following conditions: -¶ -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Materials. -¶ -THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -¶ ------------------------------------------------------------------------- -¶ -This file, vk.xml, is the Vulkan API Registry.» - </comment> -¶ - <!-- SECTION: Vulkan type definitions --> - <types>» - <type name="vk_platform" category="include">#include "vk_platform.h"</type> -¶ - <type category="define">#define <name>VK_MAKE_VERSION</name>(major, minor, patch) \ - «((major << 22) | (minor << 12) | patch)</type>» -¶ - <type category="define">// Vulkan API version supported by this file«« -#define <name>VK_API_VERSION</name> <type>VK_MAKE_VERSION</type>({{Global "VERSION_MAJOR"}}, {{Global "VERSION_MINOR"}}, {{Global "VERSION_PATCH"}})</type> -¶ - »»<type category="define">«« -#if (_MSC_VER >= 1800 || __cplusplus >= 201103L) -#define <name>VK_NONDISP_HANDLE_OPERATOR_BOOL</name>() explicit operator bool() const { return handle != 0; } -#else -#define VK_NONDISP_HANDLE_OPERATOR_BOOL() -«#endif - »»»</type> -¶ - <type category="define">««« -#define <name>VK_DEFINE_HANDLE</name>(obj) typedef struct obj##_T* obj;</type> - »»»<type category="define">««« -#if defined(__cplusplus) - »»#if (_MSC_VER >= 1800 || __cplusplus >= 201103L) - »// The bool operator only works if there are no implicit conversions from an obj to - // a bool-compatible type, which can then be used to unintentionally violate type safety. - // C++11 and above supports the "explicit" keyword on conversion operators to stop this - // from happening. Otherwise users of C++ below C++11 won't get direct access to evaluating - // the object handle as a bool in expressions like: - // if (obj) vkDestroy(obj); - #define VK_NONDISP_HANDLE_OPERATOR_BOOL() explicit operator bool() const { return handle != 0; } - #define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \ - explicit obj(uint64_t x) : handle(x) { } \ - obj(decltype(nullptr)) : handle(0) { } - «#else» - #define VK_NONDISP_HANDLE_OPERATOR_BOOL() - #define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \ - obj(uint64_t x) : handle(x) { } - «#endif - #define <name>VK_DEFINE_NONDISP_HANDLE</name>(obj) \» - struct obj { \ - obj() { } \ - VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \ - obj& operator =(uint64_t x) { handle = x; return *this; } \ - bool operator==(const obj& other) const { return handle == other.handle; } \ - bool operator!=(const obj& other) const { return handle != other.handle; } \ - bool operator!() const { return !handle; } \ - VK_NONDISP_HANDLE_OPERATOR_BOOL() \ - uint64_t handle; \ - }; -««#else - »#define VK_DEFINE_NONDISP_HANDLE(obj) typedef struct obj##_T { uint64_t handle; } obj;« -#endif - »»</type> -¶ - <type category="define"> -#if defined(__cplusplus) && ((defined(_MSC_VER) && _MSC_VER >= 1800) || __cplusplus >= 201103L) - »#define <name>VK_NULL_HANDLE</name> nullptr -«#else - »#define VK_NULL_HANDLE 0 -«#endif - »»</type> -¶ - <type requires="vk_platform" name="VkDeviceSize"/> - <type requires="vk_platform" name="VkSampleMask"/> - <type requires="vk_platform" name="VkFlags"/> - <!-- Basic C types, pulled in via vk_platform.h --> - <type requires="vk_platform" name="char"/> - <type requires="vk_platform" name="float"/> - <type requires="vk_platform" name="VkBool32"/> - <type requires="vk_platform" name="uint8_t"/> - <type requires="vk_platform" name="uint32_t"/> - <type requires="vk_platform" name="uint64_t"/> - <type requires="vk_platform" name="int32_t"/> - <type requires="vk_platform" name="size_t"/> - <!-- Bitfield types --> - {{range $e := $.Enums}} - {{if $e.IsBitfield}} - {{$bits := print (Macro "EnumName" $e | TrimRight "s") "Bits"}} - <type{{if $e.Entries}} requires="{{$bits}}"{{end}} category="bitmask">typedef <type>VkFlags</type> <name>{{$e.Name}}</name>;</type>§ - {{if $e.Entries}}{{Macro "XML.Docs" $e.Docs}} - {{else}}{{Macro "XML.Docs" (Strings $e.Docs "(no bits yet)")}} - {{end}} - {{end}} - {{end}} -¶ - <!-- Types which can be void pointers or class pointers, selected at compile time --> - {{range $i, $p := $.Pseudonyms}} - {{ if (GetAnnotation $p "dispatchHandle")}} - {{if Global "VK_DEFINE_HANDLE_TYPE_DEFINED"}} - <type category="handle">VK_DEFINE_HANDLE(<name>{{$p.Name}}</name>)</type> - {{else}} - {{Global "VK_DEFINE_HANDLE_TYPE_DEFINED" "YES"}} - <type category="handle"><type>VK_DEFINE_HANDLE</type>(<name>{{$p.Name}}</name>)</type> - {{end}} - {{else if (GetAnnotation $p "nonDispatchHandle")}} - {{if Global "VK_DEFINE_NONDISP_HANDLE_TYPE_DEFINED"}} - <type category="handle">VK_DEFINE_NONDISP_HANDLE(<name>{{$p.Name}}</name>)</type> - {{else}} - {{Global "VK_DEFINE_NONDISP_HANDLE_TYPE_DEFINED" "YES"}} - <type category="handle"><type>VK_DEFINE_NONDISP_HANDLE</type>(<name>{{$p.Name}}</name>)</type> - {{end}} - {{end}} - {{end}} -¶ - <!-- Types generated from corresponding <enums> tags below --> - {{range $e := SortBy $.Enums "EnumName"}} - {{if and $e.Entries (not (GetAnnotation $e "internal"))}} - {{if $e.IsBitfield}} - <type name="{{Macro "EnumName" $e | TrimRight "s"}}Bits" category="enum"/> - {{else}} - <type name="{{$e.Name}}" category="enum"/> - {{end}} - {{end}} - {{end}} -¶ - <!-- The PFN_vk*Function types are used by VkAllocCallbacks below --> - <type>typedef void* (VKAPI *<name>PFN_vkAllocFunction</name>)(« - void* pUserData, - size_t size, - size_t alignment, - <type>VkSystemAllocType</type> allocType);</type>» - <type>typedef void (VKAPI *<name>PFN_vkFreeFunction</name>)(« - void* pUserData, - void* pMem);</type>» -¶ - <!-- The PFN_vkVoidFunction type are used by VkGet*ProcAddr below --> - <type>typedef void (VKAPI *<name>PFN_vkVoidFunction</name>)(void);</type> -¶ - <!-- Struct types --> - {{range $c := $.Classes}} - {{if not (GetAnnotation $c "internal")}} - {{Macro "Struct" $c}} - {{end}} - {{end}} - «</types> -¶ - <!-- SECTION: Vulkan enumerant (token) definitions. --> -¶ - <enums namespace="VK" comment="Misc. hardcoded constants - not an enumerated type">» - <!-- This is part of the header boilerplate --> - {{range $d := $.Definitions}} - {{if HasPrefix $d.Name "VK_"}} - <enum value="{{$d.Expression}}" name="{{$d.Name}}"/>{{Macro "XML.Docs" $d.Docs}} - {{end}} - {{end}} - <enum value="1000.0f" name="VK_LOD_CLAMP_NONE"/> - <enum value="(-0U)" name="VK_REMAINING_MIP_LEVELS"/> - <enum value="(~0U)" name="VK_REMAINING_ARRAY_LAYERS"/> - <enum value="(_0ULL)" name="VK_WHOLE_SIZE"/> - <enum value="(~0U)" name="VK_ATTACHMENT_UNUSED"/> - <enum value="(~0U)" name="VK_QUEUE_FAMILY_IGNORED"/> - <enum value="(~0U)" name="VK_SUBPASS_EXTERNAL"/> - «</enums> -¶ - <!-- Unlike OpenGL, most tokens in Vulkan are actual typed enumerants in» - their own numeric namespaces. The "name" attribute is the C enum - type name, and is pulled in from a <type> definition above - (slightly clunky, but retains the type / enum distinction). "type" - attributes of "enum" or "bitmask" indicate that these values should - be generated inside an appropriate definition. -->« -¶ - {{range $e := $.Enums}} - {{if not (or $e.IsBitfield (GetAnnotation $e "internal"))}} - {{Macro "XML.Enum" $e}} - {{end}} - {{end}} -¶ - <!-- Flags --> - {{range $e := $.Enums}} - {{if $e.IsBitfield}} - {{Macro "XML.Bitfield" $e}} - {{end}} - {{end}} -¶ - <!-- SECTION: Vulkan command definitions --> - <commands namespace="vk">» - {{range $f := AllCommands $}} - {{if not (GetAnnotation $f "pfn")}} - {{Macro "XML.Function" $f}} - {{end}} - {{end}} - «</commands> -¶ - <!-- SECTION: Vulkan API interface definitions --> - <feature api="vulkan" name="VK_VERSION_1_0" number="1.0">» - <require comment="Header boilerplate">» - <type name="vk_platform"/> - «</require> - <require comment="API version">» - <type name="VK_API_VERSION"/> - «</require> - <require comment="API constants">» - <enum name="VK_LOD_CLAMP_NONE"/> - <enum name="VK_REMAINING_MIP_LEVELS"/> - <enum name="VK_REMAINING_ARRAY_LAYERS"/> - <enum name="VK_WHOLE_SIZE"/> - <enum name="VK_ATTACHMENT_UNUSED"/> - <enum name="VK_TRUE"/> - <enum name="VK_FALSE"/> - «</require> - <require comment="All functions (TODO: split by type)">» - {{range $f := AllCommands $}} - {{if not (GetAnnotation $f "pfn")}} - <command name="{{$f.Name}}"/> - {{end}} - {{end}} - </require> - «<require comment="Types not directly used by the API">» - <!-- Include <type name="typename"/> here for e.g. structs that» - are not parameter types of commands, but still need to be - defined in the API. - «--> - <type name="VkBufferMemoryBarrier"/> - <type name="VkDispatchIndirectCmd"/> - <type name="VkDrawIndexedIndirectCmd"/> - <type name="VkDrawIndirectCmd"/> - <type name="VkImageMemoryBarrier"/> - <type name="VkMemoryBarrier"/> - «</require> - «</feature> -¶ - <!-- SECTION: Vulkan extension interface definitions (none yet) --> -«</registry> -{{end}} - -{{/* -------------------------------------------------------------------------------- - Emits the C declaration for the specified bitfield. -------------------------------------------------------------------------------- -*/}} -{{define "XML.Bitfield"}} - {{AssertType $ "Enum"}} - - {{if $.Entries}} - <enums namespace="VK" name="{{Macro "EnumName" $ | TrimRight "s"}}Bits" type="bitmask">» - {{range $e := $.Entries}} - {{$pos := Bitpos $e.Value}} - <enum § - {{if gt $pos -1}} bitpos="{{$pos}}" § - {{else}}value="{{if $e.Value}}{{printf "0x%.8X" $e.Value}}{{else}}0{{end}}" § - {{end}}name="{{Macro "BitfieldEntryName" $e}}" § - {{if $d := $e.Docs}} comment="{{$d | JoinWith " "}}"{{end}}/> - {{end}} - «</enums> - {{end}} - -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits the C declaration for the specified enum. -------------------------------------------------------------------------------- -*/}} -{{define "XML.Enum"}} - {{AssertType $ "Enum"}} - - <enums namespace="VK" name="{{Macro "EnumName" $}}" type="enum" § - expand="{{Macro "EnumName" $ | SplitPascalCase | Upper | JoinWith "_"}}"{{if $.Docs}} comment="{{$.Docs | JoinWith " "}}"{{end}}>» - {{range $i, $e := $.Entries}} - <enum value="{{AsSigned $e.Value}}" name="{{Macro "BitfieldEntryName" $e}}"{{if $e.Docs}} comment="{{$e.Docs | JoinWith " "}}"{{end}}/> - {{end}} - {{if $lu := GetAnnotation $ "lastUnused"}} - <unused start="{{index $lu.Arguments 0}}"/> - {{end}} - «</enums> -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits the C declaration for the specified class. -------------------------------------------------------------------------------- -*/}} -{{define "Struct"}} - {{AssertType $ "Class"}} - - <type category="{{Macro "StructType" $}}" name="{{Macro "StructName" $}}"{{if $.Docs}} comment="{{$.Docs | JoinWith " "}}"{{end}}>» - {{range $f := $.Fields}} - <member>{{Node "XML.Type" $f}} <name>{{$f.Name}}</name>{{Macro "XML.ArrayPostfix" $f}}</member>{{Macro "XML.Docs" $f.Docs}} - {{end}} - «</type> -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits either 'struct' or 'union' for the specified class. -------------------------------------------------------------------------------- -*/}} -{{define "StructType"}} - {{AssertType $ "Class"}} - - {{if GetAnnotation $ "union"}}union{{else}}struct{{end}} -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits the C function pointer typedef declaration for the specified command. -------------------------------------------------------------------------------- -*/}} -{{define "XML.Function"}} - {{AssertType $ "Function"}} - - {{$ts := GetAnnotation $ "threadSafety"}} - <command{{if $ts}} threadsafe="{{index $ts.Arguments 0}}"{{end}}>» - <proto>{{Node "XML.Type" $.Return}} <name>{{$.Name}}</name></proto> - {{range $p := $.CallParameters}} - <param>{{Node "XML.Type" $p}} <name>{{$p.Name}}{{Macro "ArrayPostfix" $p}}</name></param> - {{end}} - «</command> -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits the XML translation for the specified documentation block (string array). -------------------------------------------------------------------------------- -*/}} -{{define "XML.Docs"}} - {{if $}} <!-- {{JoinWith " " $ | Replace "<" "" | Replace ">" ""}} -->{{end}} -{{end}} - -{{/* -------------------------------------------------------------------------------- - Emits the C translation for the specified type. -------------------------------------------------------------------------------- -*/}} -{{define "XML.Type.Class" }}<type>{{Macro "StructName" $.Type}}</type>{{end}} -{{define "XML.Type.Pseudonym" }}<type>{{$.Type.Name}}</type>{{end}} -{{define "XML.Type.Enum" }}<type>{{$.Type.Name}}</type>{{end}} -{{define "XML.Type.StaticArray"}}{{Node "XML.Type" $.Type.ValueType}}{{end}} -{{define "XML.Type.Pointer" }}{{if $.Type.Const}}{{Node "XML.ConstType" $.Type.To}}{{else}}{{Node "XML.Type" $.Type.To}}{{end}}*{{end}} -{{define "XML.Type.Slice" }}<type>{{Node "XML.Type" $.Type.To}}</type>*{{end}} -{{define "XML.Type#s8" }}<type>int8_t</type>{{end}} -{{define "XML.Type#u8" }}<type>uint8_t</type>{{end}} -{{define "XML.Type#s16" }}<type>int16_t</type>{{end}} -{{define "XML.Type#u16" }}<type>uint16_t</type>{{end}} -{{define "XML.Type#s32" }}<type>int32_t</type>{{end}} -{{define "XML.Type#u32" }}<type>uint32_t</type>{{end}} -{{define "XML.Type#f32" }}<type>float</type>{{end}} -{{define "XML.Type#s64" }}<type>int64_t</type>{{end}} -{{define "XML.Type#u64" }}<type>uint64_t</type>{{end}} -{{define "XML.Type#f64" }}<type>double</type>{{end}} -{{define "XML.Type#char" }}<type>char</type>{{end}} -{{define "XML.Type#void" }}void{{end}} - -{{define "XML.ConstType_Default"}}const {{Node "XML.Type" $.Type}}{{end}} -{{define "XML.ConstType.Pointer"}}{{Node "XML.Type" $.Type}} const{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits a C type and name for the given parameter -------------------------------------------------------------------------------- -*/}} -{{define "XML.Parameter"}} - {{AssertType $ "Parameter"}} - - <type>{{Macro "ParameterType" $}}</type> <name>{{$.Name}}{{Macro "ArrayPostfix" $}}</name> -{{end}} - -{{/* -------------------------------------------------------------------------------- - Emits a comma-separated list of C type-name paired parameters for the given - command. -------------------------------------------------------------------------------- -*/}} -{{define "XML.Parameters"}} - {{AssertType $ "Function"}} - - {{ForEach $.CallParameters "XML.Parameter" | JoinWith ", "}} - {{if not $.CallParameters}}<type>void</type>{{end}} -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits the fixed-size-array postfix for pseudonym types annotated with @array -------------------------------------------------------------------------------- -*/}} -{{define "XML.ArrayPostfix"}}{{Node "XML.ArrayPostfix" $}}{{end}} -{{define "XML.ArrayPostfix.StaticArray"}}[{{Node "XML.NamedValue" $.Type.SizeExpr}}]{{end}} -{{define "XML.ArrayPostfix_Default"}}{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits the value of the given constant, or the <enum> tagged name if existant. -------------------------------------------------------------------------------- -*/}} -{{define "XML.NamedValue.Definition"}}<enum>{{$.Node.Name}}</enum>{{end}} -{{define "XML.NamedValue.EnumEntry"}}<enum>{{$.Node.Name}}</enum>{{end}} -{{define "XML.NamedValue_Default"}}{{$.Node}}{{end}} diff --git a/vulkan/api/templates/vulkan_h.tmpl b/vulkan/api/templates/vulkan_h.tmpl deleted file mode 100644 index 83a5e40804..0000000000 --- a/vulkan/api/templates/vulkan_h.tmpl +++ /dev/null @@ -1,295 +0,0 @@ -{{Include "vulkan_common.tmpl"}} -{{Macro "DefineGlobals" $}} -{{$ | Macro "vulkan.h" | Format (Global "clang-format") | Write "../include/vulkan.h"}} - - -{{/* -------------------------------------------------------------------------------- - Entry point -------------------------------------------------------------------------------- -*/}} -{{define "vulkan.h"}} -#ifndef __vulkan_h_ -#define __vulkan_h_ 1 -¶ -#ifdef __cplusplus -extern "C" { -#endif -¶ -/* -** Copyright (c) 2015-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a -** copy of this software and/or associated documentation files (the -** "Materials"), to deal in the Materials without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Materials, and to -** permit persons to whom the Materials are furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be included -** in all copies or substantial portions of the Materials. -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -*/ -¶ -/* -** This header is generated from the Khronos Vulkan API Registry. -** -*/ -¶ -#define VK_VERSION_1_0 1 -#include "vk_platform.h" -¶ -#define VK_MAKE_VERSION(major, minor, patch) (((major) << 22) | ((minor) << 12) | (patch)) -¶ -// Vulkan API version supported by this file -#define VK_API_VERSION \ - VK_MAKE_VERSION({{Global "VERSION_MAJOR"}}, {{Global "VERSION_MINOR"}}, {{Global "VERSION_PATCH"}}) -¶ -#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22) -#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff) -#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff) -¶ -#if defined(__cplusplus) && ((defined(_MSC_VER) && _MSC_VER >= 1800 || __cplusplus >= 201103L) - #define VK_NULL_HANDLE nullptr -#else - #define VK_NULL_HANDLE 0 -#endif -¶ -#define VK_DEFINE_HANDLE(obj) typedef struct obj##_T* obj; -¶ -#if defined(__cplusplus) -#if ((defined(_MSC_VER) && _MSC_VER >= 1800 || __cplusplus >= 201103L) -// The bool operator only works if there are no implicit conversions from an obj to -// a bool-compatible type, which can then be used to unintentionally violate type safety. -// C++11 and above supports the "explicit" keyword on conversion operators to stop this -// from happening. Otherwise users of C++ below C++11 won't get direct access to evaluating -// the object handle as a bool in expressions like: -// if (obj) vkDestroy(obj); -#define VK_NONDISP_HANDLE_OPERATOR_BOOL() \ - explicit operator bool() const { return handle != 0; } -#define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \ - explicit obj(uint64_t x) : handle(x) { } \ - obj(decltype(nullptr)) : handle(0) { } -#else -#define VK_NONDISP_HANDLE_OPERATOR_BOOL() -#define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \ - obj(uint64_t x) : handle(x) { } -#endif -#define VK_DEFINE_NONDISP_HANDLE(obj) \ - struct obj { \ - obj() : handle(0) { } \ - VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \ - obj& operator=(uint64_t x) { \ - handle = x; \ - return *this; \ - } \ - bool operator==(const obj& other) const { return handle == other.handle; } \ - bool operator!=(const obj& other) const { return handle != other.handle; } \ - bool operator!() const { return !handle; } \ - VK_NONDISP_HANDLE_OPERATOR_BOOL() \ - uint64_t handle; \ - }; -#else -#define VK_DEFINE_NONDISP_HANDLE(obj) \ - typedef struct obj##_T { uint64_t handle; } obj; -#endif -¶ -#define VK_LOD_CLAMP_NONE 1000.0f -#define VK_REMAINING_MIP_LEVELS (~0U) -#define VK_REMAINING_ARRAY_LAYERS (~0U) -#define VK_WHOLE_SIZE (~0ULL) -#define VK_ATTACHMENT_UNUSED (~0U) -define VK_QUEUE_FAMILY_IGNORED (~0U) -define VK_SUBPASS_EXTERNAL (~0U) -{{range $d := $.Definitions}} - {{if HasPrefix $d.Name "VK_"}}#define {{$d.Name}} {{$d.Expression}}{{end}} -{{end}} -¶ -{{range $i, $p := $.Pseudonyms}} - {{if GetAnnotation $p "dispatchHandle"}}VK_DEFINE_HANDLE({{$p.Name}}) - {{else if GetAnnotation $p "nonDispatchHandle"}}VK_DEFINE_NONDISP_HANDLE({{$p.Name}}) - {{end}} -{{end}} -¶ -// ------------------------------------------------------------------------------------------------ -// Enumerations -¶ - {{range $e := $.Enums}} - {{if not $e.IsBitfield}} - {{Macro "Enum" $e}} - {{end}} - {{end}} -¶ -// ------------------------------------------------------------------------------------------------ -// Flags -¶ - {{range $e := $.Enums}} - {{if $e.IsBitfield}} - {{Macro "Bitfield" $e}} - {{end}} - {{end}} -¶ -// ------------------------------------------------------------------------------------------------ -// Vulkan structures -¶ - {{/* Function pointers */}} - {{range $f := AllCommands $}} - {{if GetAnnotation $f "pfn"}} - {{Macro "FunctionTypedef" $f}} - {{end}} - {{end}} -¶ - {{range $c := $.Classes}} - {{if not (GetAnnotation $c "internal")}} - {{Macro "Struct" $c}} - {{end}} - {{end}} -¶ -// ------------------------------------------------------------------------------------------------ -// API functions -¶ - {{range $f := AllCommands $}} - {{if not (GetAnnotation $f "pfn")}} - {{Macro "FunctionTypedef" $f}} - {{end}} - {{end}} -¶ -#ifdef VK_NO_PROTOTYPES -¶ - {{range $f := AllCommands $}} - {{if not (GetAnnotation $f "pfn")}} - {{Macro "FunctionDecl" $f}} - {{end}} - {{end}} -¶ -#endif -¶ -#ifdef __cplusplus -} -#endif -¶ -#endif -{{end}} - -{{/* -------------------------------------------------------------------------------- - Emits the C declaration for the specified bitfield. -------------------------------------------------------------------------------- -*/}} -{{define "Bitfield"}} - {{AssertType $ "Enum"}} - - {{Macro "Docs" $.Docs}} - typedef VkFlags {{Macro "EnumName" $}}; - {{if $.Entries}} - typedef enum { - {{range $b := $.Entries}} - {{Macro "BitfieldEntryName" $b}} = {{printf "0x%.8X" $b.Value}}, {{Macro "Docs" $b.Docs}} - {{end}} - } {{Macro "EnumName" $ | TrimRight "s"}}Bits; - {{end}} - ¶ -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits the C declaration for the specified enum. -------------------------------------------------------------------------------- -*/}} -{{define "Enum"}} - {{AssertType $ "Enum"}} - - {{Macro "Docs" $.Docs}} - typedef enum { - {{range $i, $e := $.Entries}} - {{Macro "EnumEntry" $e}} = {{printf "0x%.8X" $e.Value}}, {{Macro "Docs" $e.Docs}} - {{end}} - ¶ - {{$name := Macro "EnumName" $ | TrimRight "ABCDEFGHIJKLMNOQRSTUVWXYZ" | SplitPascalCase | Upper | JoinWith "_"}} - {{if GetAnnotation $ "enumMaxOnly"}} - VK_MAX_ENUM({{$name | SplitOn "VK_"}}) - {{else}} - {{$first := Macro "EnumFirstEntry" $ | SplitOn $name | TrimLeft "_"}} - {{$last := Macro "EnumLastEntry" $ | SplitOn $name | TrimLeft "_"}} - VK_ENUM_RANGE({{$name | SplitOn "VK_"}}, {{$first}}, {{$last}}) - {{end}} - } {{Macro "EnumName" $}}; - ¶ -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits the C declaration for the specified class. -------------------------------------------------------------------------------- -*/}} -{{define "Struct"}} - {{AssertType $ "Class"}} - - {{Macro "Docs" $.Docs}} - typedef {{Macro "StructType" $}} { - {{ForEach $.Fields "Field" | JoinWith "\n"}} - } {{Macro "StructName" $}}; - ¶ -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits the C declaration for the specified class field. -------------------------------------------------------------------------------- -*/}} -{{define "Field"}} - {{AssertType $ "Field"}} - - {{Node "Type" $}} {{$.Name}}§ - {{Macro "ArrayPostfix" (TypeOf $)}}; {{Macro "Docs" $.Docs}} -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits either 'struct' or 'union' for the specified class. -------------------------------------------------------------------------------- -*/}} -{{define "StructType"}} - {{AssertType $ "Class"}} - - {{if GetAnnotation $ "union"}}union{{else}}struct{{end}} -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits the C function pointer typedef declaration for the specified command. -------------------------------------------------------------------------------- -*/}} -{{define "FunctionTypedef"}} - {{AssertType $ "Function"}} - - typedef {{Node "Type" $.Return}} (VKAPI* {{Macro "FunctionPtrName" $}})({{Macro "Parameters" $}}); -{{end}} - - -{{/* -------------------------------------------------------------------------------- - Emits the C function declaration for the specified command. -------------------------------------------------------------------------------- -*/}} -{{define "FunctionDecl"}} - {{AssertType $ "Function"}} - - {{if not (GetAnnotation $ "fptr")}} - {{Macro "Docs" $.Docs}} - {{Node "Type" $.Return}} VKAPI {{Macro "FunctionName" $}}({{Macro "Parameters" $}}); - {{end}} -{{end}} diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp index df86af0c3b..ad46c3bf93 100644 --- a/vulkan/libvulkan/api_gen.cpp +++ b/vulkan/libvulkan/api_gen.cpp @@ -16,12 +16,11 @@ // WARNING: This file is generated. See ../README.md for instructions. +#include <log/log.h> #include <string.h> #include <algorithm> -#include <log/log.h> - // to catch mismatches between vulkan.h and this file #undef VK_NO_PROTOTYPES #include "api.h" diff --git a/vulkan/libvulkan/api_gen.h b/vulkan/libvulkan/api_gen.h index 4bedbeb16e..f5822249b3 100644 --- a/vulkan/libvulkan/api_gen.h +++ b/vulkan/libvulkan/api_gen.h @@ -20,7 +20,9 @@ #define LIBVULKAN_API_GEN_H #include <vulkan/vulkan.h> + #include <bitset> + #include "driver_gen.h" namespace vulkan { diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl index bdd3573b11..940b747f1b 100644 --- a/vulkan/libvulkan/code-generator.tmpl +++ b/vulkan/libvulkan/code-generator.tmpl @@ -37,8 +37,10 @@ #ifndef LIBVULKAN_API_GEN_H #define LIBVULKAN_API_GEN_H ¶ -#include <bitset> #include <vulkan/vulkan.h> +¶ +#include <bitset> +¶ #include "driver_gen.h" ¶ namespace vulkan {« @@ -90,12 +92,11 @@ bool InitDispatchTable( ¶ // WARNING: This file is generated. See ../README.md for instructions. ¶ +#include <log/log.h> #include <string.h> ¶ #include <algorithm> ¶ -#include <log/log.h> -¶ // to catch mismatches between vulkan.h and this file #undef VK_NO_PROTOTYPES #include "api.h" @@ -217,9 +218,10 @@ namespace {« #ifndef LIBVULKAN_DRIVER_GEN_H #define LIBVULKAN_DRIVER_GEN_H ¶ -#include <bitset> -#include <vulkan/vulkan.h> #include <vulkan/vk_android_native_buffer.h> +#include <vulkan/vulkan.h> +¶ +#include <bitset> ¶ namespace vulkan {« namespace driver {« @@ -271,12 +273,11 @@ bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc, ¶ // WARNING: This file is generated. See ../README.md for instructions. ¶ +#include <log/log.h> #include <string.h> ¶ #include <algorithm> ¶ -#include <log/log.h> -¶ #include "driver.h" ¶ namespace vulkan {« diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp index 23506bad54..d33e5528e8 100644 --- a/vulkan/libvulkan/driver.cpp +++ b/vulkan/libvulkan/driver.cpp @@ -16,30 +16,29 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS +#include "driver.h" + +#include <dlfcn.h> #include <malloc.h> #include <stdlib.h> #include <string.h> -#include <sys/prctl.h> - -#include <dlfcn.h> -#include <algorithm> -#include <array> -#include <new> - -#include <log/log.h> #include <android/dlext.h> #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> +#include <android-base/properties.h> #include <configstore/Utils.h> #include <cutils/properties.h> #include <graphicsenv/GraphicsEnv.h> +#include <log/log.h> +#include <sys/prctl.h> #include <utils/Timers.h> #include <utils/Trace.h> -#include <utils/Vector.h> -#include "android-base/properties.h" +#include <algorithm> +#include <array> +#include <new> +#include <vector> -#include "driver.h" #include "stubhal.h" using namespace android::hardware::configstore; @@ -809,8 +808,7 @@ VkResult EnumerateInstanceExtensionProperties( const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties) { - - android::Vector<VkExtensionProperties> loader_extensions; + std::vector<VkExtensionProperties> loader_extensions; loader_extensions.push_back({ VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION}); @@ -833,7 +831,7 @@ VkResult EnumerateInstanceExtensionProperties( uint32_t count = std::min( *pPropertyCount, static_cast<uint32_t>(loader_extensions.size())); - std::copy_n(loader_extensions.begin(), count, pProperties); + std::copy_n(loader_extensions.data(), count, pProperties); if (count < loader_extensions.size()) { *pPropertyCount = count; @@ -879,8 +877,7 @@ VkResult EnumerateInstanceExtensionProperties( bool QueryPresentationProperties( VkPhysicalDevice physicalDevice, - VkPhysicalDevicePresentationPropertiesANDROID *presentation_properties) -{ + VkPhysicalDevicePresentationPropertiesANDROID *presentation_properties) { const InstanceData& data = GetData(physicalDevice); // GPDP2 must be present and enabled on the instance. @@ -920,7 +917,7 @@ VkResult EnumerateDeviceExtensionProperties( VkExtensionProperties* pProperties) { const InstanceData& data = GetData(physicalDevice); // extensions that are unconditionally exposed by the loader - android::Vector<VkExtensionProperties> loader_extensions; + std::vector<VkExtensionProperties> loader_extensions; loader_extensions.push_back({ VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME, VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION}); @@ -956,7 +953,7 @@ VkResult EnumerateDeviceExtensionProperties( uint32_t count = std::min( *pPropertyCount, static_cast<uint32_t>(loader_extensions.size())); - std::copy_n(loader_extensions.begin(), count, pProperties); + std::copy_n(loader_extensions.data(), count, pProperties); if (count < loader_extensions.size()) { *pPropertyCount = count; @@ -1245,11 +1242,10 @@ VkResult EnumeratePhysicalDeviceGroups( if (!device_count) return VK_INCOMPLETE; - android::Vector<VkPhysicalDevice> devices; - devices.resize(device_count); + std::vector<VkPhysicalDevice> devices(device_count); *pPhysicalDeviceGroupCount = device_count; - result = EnumeratePhysicalDevices(instance, &device_count, - devices.editArray()); + result = + EnumeratePhysicalDevices(instance, &device_count, devices.data()); if (result < 0) return result; diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp index 574c3273d0..7020be1eda 100644 --- a/vulkan/libvulkan/driver_gen.cpp +++ b/vulkan/libvulkan/driver_gen.cpp @@ -16,12 +16,11 @@ // WARNING: This file is generated. See ../README.md for instructions. +#include <log/log.h> #include <string.h> #include <algorithm> -#include <log/log.h> - #include "driver.h" namespace vulkan { diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h index 3faf6c0e32..c299549dae 100644 --- a/vulkan/libvulkan/driver_gen.h +++ b/vulkan/libvulkan/driver_gen.h @@ -21,6 +21,7 @@ #include <vulkan/vk_android_native_buffer.h> #include <vulkan/vulkan.h> + #include <bitset> namespace vulkan { diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp index a8949d36f4..761d128d79 100644 --- a/vulkan/libvulkan/swapchain.cpp +++ b/vulkan/libvulkan/swapchain.cpp @@ -24,7 +24,6 @@ #include <ui/BufferQueueDefs.h> #include <utils/StrongPointer.h> #include <utils/Trace.h> -#include <utils/Vector.h> #include <algorithm> #include <unordered_set> @@ -34,10 +33,6 @@ using android::hardware::graphics::common::V1_0::BufferUsage; -// TODO(jessehall): Currently we don't have a good error code for when a native -// window operation fails. Just returning INITIALIZATION_FAILED for now. Later -// versions (post SDK 0.9) of the API/extension have a better error code. -// When updating to that version, audit all error returns. namespace vulkan { namespace driver { @@ -48,29 +43,12 @@ const VkSurfaceTransformFlagsKHR kSupportedTransforms = VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR | VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR | VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR | - // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform. - // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR | - // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR | - // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR | - // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR | + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR | + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR | + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR | + VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR | VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR; -int TranslateVulkanToNativeTransform(VkSurfaceTransformFlagBitsKHR transform) { - switch (transform) { - // TODO: See TODO in TranslateNativeToVulkanTransform - case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR: - return NATIVE_WINDOW_TRANSFORM_ROT_90; - case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR: - return NATIVE_WINDOW_TRANSFORM_ROT_180; - case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR: - return NATIVE_WINDOW_TRANSFORM_ROT_270; - case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR: - case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR: - default: - return 0; - } -} - VkSurfaceTransformFlagBitsKHR TranslateNativeToVulkanTransform(int native) { // Native and Vulkan transforms are isomorphic, but are represented // differently. Vulkan transforms are built up of an optional horizontal @@ -78,27 +56,22 @@ VkSurfaceTransformFlagBitsKHR TranslateNativeToVulkanTransform(int native) { // transforms are built up from a horizontal flip, vertical flip, and // 90-degree rotation, all optional but always in that order. - // TODO(jessehall): For now, only support pure rotations, not - // flip or flip-and-rotate, until I have more time to test them and build - // sample code. As far as I know we never actually use anything besides - // pure rotations anyway. - switch (native) { - case 0: // 0x0 + case 0: return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - // case NATIVE_WINDOW_TRANSFORM_FLIP_H: // 0x1 - // return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR; - // case NATIVE_WINDOW_TRANSFORM_FLIP_V: // 0x2 - // return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR; - case NATIVE_WINDOW_TRANSFORM_ROT_180: // FLIP_H | FLIP_V + case NATIVE_WINDOW_TRANSFORM_FLIP_H: + return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR; + case NATIVE_WINDOW_TRANSFORM_FLIP_V: + return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR; + case NATIVE_WINDOW_TRANSFORM_ROT_180: return VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR; - case NATIVE_WINDOW_TRANSFORM_ROT_90: // 0x4 + case NATIVE_WINDOW_TRANSFORM_ROT_90: return VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR; - // case NATIVE_WINDOW_TRANSFORM_FLIP_H | NATIVE_WINDOW_TRANSFORM_ROT_90: - // return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR; - // case NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_ROT_90: - // return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR; - case NATIVE_WINDOW_TRANSFORM_ROT_270: // FLIP_H | FLIP_V | ROT_90 + case NATIVE_WINDOW_TRANSFORM_FLIP_H | NATIVE_WINDOW_TRANSFORM_ROT_90: + return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR; + case NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_ROT_90: + return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR; + case NATIVE_WINDOW_TRANSFORM_ROT_270: return VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR; case NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY: default: @@ -106,6 +79,31 @@ VkSurfaceTransformFlagBitsKHR TranslateNativeToVulkanTransform(int native) { } } +int TranslateVulkanToNativeTransform(VkSurfaceTransformFlagBitsKHR transform) { + switch (transform) { + case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR: + return NATIVE_WINDOW_TRANSFORM_ROT_90; + case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR: + return NATIVE_WINDOW_TRANSFORM_ROT_180; + case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR: + return NATIVE_WINDOW_TRANSFORM_ROT_270; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR: + return NATIVE_WINDOW_TRANSFORM_FLIP_H; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR: + return NATIVE_WINDOW_TRANSFORM_FLIP_H | + NATIVE_WINDOW_TRANSFORM_ROT_90; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR: + return NATIVE_WINDOW_TRANSFORM_FLIP_V; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR: + return NATIVE_WINDOW_TRANSFORM_FLIP_V | + NATIVE_WINDOW_TRANSFORM_ROT_90; + case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR: + case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR: + default: + return 0; + } +} + int InvertTransformToNative(VkSurfaceTransformFlagBitsKHR transform) { switch (transform) { case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR: @@ -114,17 +112,16 @@ int InvertTransformToNative(VkSurfaceTransformFlagBitsKHR transform) { return NATIVE_WINDOW_TRANSFORM_ROT_180; case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR: return NATIVE_WINDOW_TRANSFORM_ROT_90; - // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform. - // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR: - // return NATIVE_WINDOW_TRANSFORM_FLIP_H; - // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR: - // return NATIVE_WINDOW_TRANSFORM_FLIP_H | - // NATIVE_WINDOW_TRANSFORM_ROT_90; - // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR: - // return NATIVE_WINDOW_TRANSFORM_FLIP_V; - // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR: - // return NATIVE_WINDOW_TRANSFORM_FLIP_V | - // NATIVE_WINDOW_TRANSFORM_ROT_90; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR: + return NATIVE_WINDOW_TRANSFORM_FLIP_H; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR: + return NATIVE_WINDOW_TRANSFORM_FLIP_H | + NATIVE_WINDOW_TRANSFORM_ROT_90; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR: + return NATIVE_WINDOW_TRANSFORM_FLIP_V; + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR: + return NATIVE_WINDOW_TRANSFORM_FLIP_V | + NATIVE_WINDOW_TRANSFORM_ROT_90; case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR: case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR: default: @@ -134,7 +131,6 @@ int InvertTransformToNative(VkSurfaceTransformFlagBitsKHR transform) { class TimingInfo { public: - TimingInfo() = default; TimingInfo(const VkPresentTimeGOOGLE* qp, uint64_t nativeFrameId) : vals_{qp->presentID, qp->desiredPresentTime, 0, 0, 0}, native_frame_id_(nativeFrameId) {} @@ -201,8 +197,6 @@ class TimingInfo { { NATIVE_WINDOW_TIMESTAMP_PENDING }; }; -// ---------------------------------------------------------------------------- - struct Surface { android::sp<ANativeWindow> window; VkSwapchainKHR swapchain_handle; @@ -270,7 +264,7 @@ struct Swapchain { bool dequeued; } images[android::BufferQueueDefs::NUM_BUFFER_SLOTS]; - android::Vector<TimingInfo> timing; + std::vector<TimingInfo> timing; }; VkSwapchainKHR HandleFromSwapchain(Swapchain* swapchain) { @@ -285,6 +279,8 @@ void ReleaseSwapchainImage(VkDevice device, ANativeWindow* window, int release_fence, Swapchain::Image& image) { + ATRACE_CALL(); + ALOG_ASSERT(release_fence == -1 || image.dequeued, "ReleaseSwapchainImage: can't provide a release fence for " "non-dequeued images"); @@ -323,7 +319,9 @@ void ReleaseSwapchainImage(VkDevice device, } if (image.image) { + ATRACE_BEGIN("DestroyImage"); GetData(device).driver.DestroyImage(device, image.image, nullptr); + ATRACE_END(); image.image = VK_NULL_HANDLE; } @@ -349,7 +347,7 @@ uint32_t get_num_ready_timings(Swapchain& swapchain) { uint32_t num_ready = 0; const size_t num_timings = swapchain.timing.size() - MIN_NUM_FRAMES_AGO + 1; for (uint32_t i = 0; i < num_timings; i++) { - TimingInfo& ti = swapchain.timing.editItemAt(i); + TimingInfo& ti = swapchain.timing[i]; if (ti.ready()) { // This TimingInfo is ready to be reported to the user. Add it // to the num_ready. @@ -419,7 +417,7 @@ void copy_ready_timings(Swapchain& swapchain, } uint32_t num_copied = 0; - size_t num_to_remove = 0; + int32_t num_to_remove = 0; for (uint32_t i = 0; i <= last_ready && num_copied < *count; i++) { const TimingInfo& ti = swapchain.timing[i]; if (ti.ready()) { @@ -431,7 +429,8 @@ void copy_ready_timings(Swapchain& swapchain, // Discard old frames that aren't ready if newer frames are ready. // We don't expect to get the timing info for those old frames. - swapchain.timing.removeItemsAt(0, num_to_remove); + swapchain.timing.erase(swapchain.timing.begin(), + swapchain.timing.begin() + num_to_remove); *count = num_copied; } @@ -539,15 +538,12 @@ VkResult CreateAndroidSurfaceKHR( strerror(-err), err); surface->~Surface(); allocator->pfnFree(allocator->pUserData, surface); - return VK_ERROR_INITIALIZATION_FAILED; + return VK_ERROR_SURFACE_LOST_KHR; } - // TODO(jessehall): Create and use NATIVE_WINDOW_API_VULKAN. err = native_window_api_connect(surface->window.get(), NATIVE_WINDOW_API_EGL); if (err != 0) { - // TODO(jessehall): Improve error reporting. Can we enumerate possible - // errors and translate them to valid Vulkan result codes? ALOGE("native_window_api_connect() failed: %s (%d)", strerror(-err), err); surface->~Surface(); @@ -656,7 +652,6 @@ VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR( return VK_ERROR_SURFACE_LOST_KHR; } - // TODO(jessehall): Figure out what the min/max values should be. int max_buffer_count; err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &max_buffer_count); if (err != 0) { @@ -670,8 +665,7 @@ VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR( capabilities->currentExtent = VkExtent2D{static_cast<uint32_t>(width), static_cast<uint32_t>(height)}; - // TODO(jessehall): Figure out what the max extent should be. Maximum - // texture dimension maybe? + // TODO(http://b/134182502): Figure out what the max extent should be. capabilities->minImageExtent = VkExtent2D{1, 1}; capabilities->maxImageExtent = VkExtent2D{4096, 4096}; @@ -685,11 +679,6 @@ VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR( // associated with the bufferqueue. It can't be changed from here. capabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; - // TODO(jessehall): I think these are right, but haven't thought hard about - // it. Do we need to query the driver for support of any of these? - // Currently not included: - // - VK_IMAGE_USAGE_DEPTH_STENCIL_BIT: definitely not - // - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT: definitely not capabilities->supportedUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | @@ -729,8 +718,7 @@ VkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice pdev, int err = native_window_get_wide_color_support(surface.window.get(), &wide_color_support); if (err) { - // Not allowed to return a more sensible error code, so do this - return VK_ERROR_OUT_OF_HOST_MEMORY; + return VK_ERROR_SURFACE_LOST_KHR; } ALOGV("wide_color_support is: %d", wide_color_support); wide_color_support = @@ -828,11 +816,10 @@ VkResult GetPhysicalDeviceSurfaceFormats2KHR( } else { // temp vector for forwarding; we'll marshal it into the pSurfaceFormats // after the call. - android::Vector<VkSurfaceFormatKHR> surface_formats; - surface_formats.resize(*pSurfaceFormatCount); + std::vector<VkSurfaceFormatKHR> surface_formats(*pSurfaceFormatCount); VkResult result = GetPhysicalDeviceSurfaceFormatsKHR( physicalDevice, pSurfaceInfo->surface, pSurfaceFormatCount, - &surface_formats.editItemAt(0)); + surface_formats.data()); if (result == VK_SUCCESS || result == VK_INCOMPLETE) { // marshal results individually due to stride difference. @@ -874,7 +861,7 @@ VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev, } uint32_t max_buffer_count = static_cast<uint32_t>(query_value); - android::Vector<VkPresentModeKHR> present_modes; + std::vector<VkPresentModeKHR> present_modes; if (min_undequeued_buffers + 1 < max_buffer_count) present_modes.push_back(VK_PRESENT_MODE_MAILBOX_KHR); present_modes.push_back(VK_PRESENT_MODE_FIFO_KHR); @@ -894,7 +881,7 @@ VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev, if (*count < num_modes) result = VK_INCOMPLETE; *count = std::min(*count, num_modes); - std::copy(present_modes.begin(), present_modes.begin() + int(*count), modes); + std::copy_n(present_modes.data(), *count, modes); } else { *count = num_modes; } @@ -978,6 +965,40 @@ VkResult GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice, return VK_SUCCESS; } +static void DestroySwapchainInternal(VkDevice device, + VkSwapchainKHR swapchain_handle, + const VkAllocationCallbacks* allocator) { + ATRACE_CALL(); + + const auto& dispatch = GetData(device).driver; + Swapchain* swapchain = SwapchainFromHandle(swapchain_handle); + if (!swapchain) { + return; + } + + bool active = swapchain->surface.swapchain_handle == swapchain_handle; + ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr; + + if (window && swapchain->frame_timestamps_enabled) { + native_window_enable_frame_timestamps(window, false); + } + + for (uint32_t i = 0; i < swapchain->num_images; i++) { + ReleaseSwapchainImage(device, window, -1, swapchain->images[i]); + } + + if (active) { + swapchain->surface.swapchain_handle = VK_NULL_HANDLE; + } + + if (!allocator) { + allocator = &GetData(device).allocator; + } + + swapchain->~Swapchain(); + allocator->pfnFree(allocator->pUserData, swapchain); +} + VKAPI_ATTR VkResult CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* create_info, @@ -1052,6 +1073,8 @@ VkResult CreateSwapchainKHR(VkDevice device, // non-FREE state at any given time. Disconnecting and re-connecting // orphans the previous buffers, getting us back to the state where we can // dequeue all buffers. + // + // TODO(http://b/134186185) recycle swapchain images more efficiently err = native_window_api_disconnect(surface.window.get(), NATIVE_WINDOW_API_EGL); ALOGW_IF(err != 0, "native_window_api_disconnect failed: %s (%d)", @@ -1072,8 +1095,6 @@ VkResult CreateSwapchainKHR(VkDevice device, create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1; err = surface.window->setSwapInterval(surface.window.get(), swap_interval); if (err != 0) { - // TODO(jessehall): Improve error reporting. Can we enumerate possible - // errors and translate them to valid Vulkan result codes? ALOGE("native_window->setSwapInterval(1) failed: %s (%d)", strerror(-err), err); return VK_ERROR_SURFACE_LOST_KHR; @@ -1100,8 +1121,6 @@ VkResult CreateSwapchainKHR(VkDevice device, err = native_window_set_buffers_format(surface.window.get(), native_pixel_format); if (err != 0) { - // TODO(jessehall): Improve error reporting. Can we enumerate possible - // errors and translate them to valid Vulkan result codes? ALOGE("native_window_set_buffers_format(%d) failed: %s (%d)", native_pixel_format, strerror(-err), err); return VK_ERROR_SURFACE_LOST_KHR; @@ -1109,8 +1128,6 @@ VkResult CreateSwapchainKHR(VkDevice device, err = native_window_set_buffers_data_space(surface.window.get(), native_dataspace); if (err != 0) { - // TODO(jessehall): Improve error reporting. Can we enumerate possible - // errors and translate them to valid Vulkan result codes? ALOGE("native_window_set_buffers_data_space(%d) failed: %s (%d)", native_dataspace, strerror(-err), err); return VK_ERROR_SURFACE_LOST_KHR; @@ -1120,8 +1137,6 @@ VkResult CreateSwapchainKHR(VkDevice device, surface.window.get(), static_cast<int>(create_info->imageExtent.width), static_cast<int>(create_info->imageExtent.height)); if (err != 0) { - // TODO(jessehall): Improve error reporting. Can we enumerate possible - // errors and translate them to valid Vulkan result codes? ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)", create_info->imageExtent.width, create_info->imageExtent.height, strerror(-err), err); @@ -1140,8 +1155,6 @@ VkResult CreateSwapchainKHR(VkDevice device, surface.window.get(), InvertTransformToNative(create_info->preTransform)); if (err != 0) { - // TODO(jessehall): Improve error reporting. Can we enumerate possible - // errors and translate them to valid Vulkan result codes? ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)", InvertTransformToNative(create_info->preTransform), strerror(-err), err); @@ -1151,8 +1164,6 @@ VkResult CreateSwapchainKHR(VkDevice device, err = native_window_set_scaling_mode( surface.window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); if (err != 0) { - // TODO(jessehall): Improve error reporting. Can we enumerate possible - // errors and translate them to valid Vulkan result codes? ALOGE("native_window_set_scaling_mode(SCALE_TO_WINDOW) failed: %s (%d)", strerror(-err), err); return VK_ERROR_SURFACE_LOST_KHR; @@ -1182,8 +1193,6 @@ VkResult CreateSwapchainKHR(VkDevice device, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &query_value); if (err != 0 || query_value < 0) { - // TODO(jessehall): Improve error reporting. Can we enumerate possible - // errors and translate them to valid Vulkan result codes? ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err, query_value); return VK_ERROR_SURFACE_LOST_KHR; @@ -1201,8 +1210,6 @@ VkResult CreateSwapchainKHR(VkDevice device, // can't actually use!). err = native_window_set_buffer_count(surface.window.get(), std::max(2u, num_images)); if (err != 0) { - // TODO(jessehall): Improve error reporting. Can we enumerate possible - // errors and translate them to valid Vulkan result codes? ALOGE("native_window_set_buffer_count(%d) failed: %s (%d)", num_images, strerror(-err), err); return VK_ERROR_SURFACE_LOST_KHR; @@ -1211,7 +1218,7 @@ VkResult CreateSwapchainKHR(VkDevice device, int32_t legacy_usage = 0; if (dispatch.GetSwapchainGrallocUsage2ANDROID) { uint64_t consumer_usage, producer_usage; - ATRACE_BEGIN("dispatch.GetSwapchainGrallocUsage2ANDROID"); + ATRACE_BEGIN("GetSwapchainGrallocUsage2ANDROID"); result = dispatch.GetSwapchainGrallocUsage2ANDROID( device, create_info->imageFormat, create_info->imageUsage, swapchain_image_usage, &consumer_usage, &producer_usage); @@ -1223,7 +1230,7 @@ VkResult CreateSwapchainKHR(VkDevice device, legacy_usage = android_convertGralloc1To0Usage(producer_usage, consumer_usage); } else if (dispatch.GetSwapchainGrallocUsageANDROID) { - ATRACE_BEGIN("dispatch.GetSwapchainGrallocUsageANDROID"); + ATRACE_BEGIN("GetSwapchainGrallocUsageANDROID"); result = dispatch.GetSwapchainGrallocUsageANDROID( device, create_info->imageFormat, create_info->imageUsage, &legacy_usage); @@ -1242,8 +1249,6 @@ VkResult CreateSwapchainKHR(VkDevice device, } err = native_window_set_usage(surface.window.get(), native_usage); if (err != 0) { - // TODO(jessehall): Improve error reporting. Can we enumerate possible - // errors and translate them to valid Vulkan result codes? ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), err); return VK_ERROR_SURFACE_LOST_KHR; } @@ -1301,8 +1306,6 @@ VkResult CreateSwapchainKHR(VkDevice device, err = surface.window->dequeueBuffer(surface.window.get(), &buffer, &img.dequeue_fence); if (err != 0) { - // TODO(jessehall): Improve error reporting. Can we enumerate - // possible errors and translate them to valid Vulkan result codes? ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err); result = VK_ERROR_SURFACE_LOST_KHR; break; @@ -1322,7 +1325,7 @@ VkResult CreateSwapchainKHR(VkDevice device, &image_native_buffer.usage2.producer, &image_native_buffer.usage2.consumer); - ATRACE_BEGIN("dispatch.CreateImage"); + ATRACE_BEGIN("CreateImage"); result = dispatch.CreateImage(device, &image_create, nullptr, &img.image); ATRACE_END(); @@ -1335,9 +1338,6 @@ VkResult CreateSwapchainKHR(VkDevice device, // -- Cancel all buffers, returning them to the queue -- // If an error occurred before, also destroy the VkImage and release the // buffer reference. Otherwise, we retain a strong reference to the buffer. - // - // TODO(jessehall): The error path here is the same as DestroySwapchain, - // but not the non-error path. Should refactor/unify. for (uint32_t i = 0; i < num_images; i++) { Swapchain::Image& img = swapchain->images[i]; if (img.dequeued) { @@ -1348,18 +1348,11 @@ VkResult CreateSwapchainKHR(VkDevice device, img.dequeued = false; } } - if (result != VK_SUCCESS) { - if (img.image) { - ATRACE_BEGIN("dispatch.DestroyImage"); - dispatch.DestroyImage(device, img.image, nullptr); - ATRACE_END(); - } - } } if (result != VK_SUCCESS) { - swapchain->~Swapchain(); - allocator->pfnFree(allocator->pUserData, swapchain); + DestroySwapchainInternal(device, HandleFromSwapchain(swapchain), + allocator); return result; } @@ -1374,24 +1367,7 @@ void DestroySwapchainKHR(VkDevice device, const VkAllocationCallbacks* allocator) { ATRACE_CALL(); - const auto& dispatch = GetData(device).driver; - Swapchain* swapchain = SwapchainFromHandle(swapchain_handle); - if (!swapchain) - return; - bool active = swapchain->surface.swapchain_handle == swapchain_handle; - ANativeWindow* window = active ? swapchain->surface.window.get() : nullptr; - - if (swapchain->frame_timestamps_enabled) { - native_window_enable_frame_timestamps(window, false); - } - for (uint32_t i = 0; i < swapchain->num_images; i++) - ReleaseSwapchainImage(device, window, -1, swapchain->images[i]); - if (active) - swapchain->surface.swapchain_handle = VK_NULL_HANDLE; - if (!allocator) - allocator = &GetData(device).allocator; - swapchain->~Swapchain(); - allocator->pfnFree(allocator->pUserData, swapchain); + DestroySwapchainInternal(device, swapchain_handle, allocator); } VKAPI_ATTR @@ -1457,8 +1433,6 @@ VkResult AcquireNextImageKHR(VkDevice device, int fence_fd; err = window->dequeueBuffer(window, &buffer, &fence_fd); if (err != 0) { - // TODO(jessehall): Improve error reporting. Can we enumerate possible - // errors and translate them to valid Vulkan result codes? ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err); return VK_ERROR_SURFACE_LOST_KHR; } @@ -1513,8 +1487,6 @@ VkResult AcquireNextImage2KHR(VkDevice device, uint32_t* pImageIndex) { ATRACE_CALL(); - // TODO: this should actually be the other way around and this function - // should handle any additional structures that get passed in return AcquireNextImageKHR(device, pAcquireInfo->swapchain, pAcquireInfo->timeout, pAcquireInfo->semaphore, pAcquireInfo->fence, pImageIndex); @@ -1673,9 +1645,9 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) { // Add a new timing record with the user's presentID and // the nativeFrameId. - swapchain.timing.push_back(TimingInfo(time, nativeFrameId)); + swapchain.timing.emplace_back(time, nativeFrameId); while (swapchain.timing.size() > MAX_TIMING_INFOS) { - swapchain.timing.removeAt(0); + swapchain.timing.erase(swapchain.timing.begin()); } if (time->desiredPresentTime) { // Set the desiredPresentTime: @@ -1692,17 +1664,16 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) { err = window->queueBuffer(window, img.buffer.get(), fence); // queueBuffer always closes fence, even on error if (err != 0) { - // TODO(jessehall): What now? We should probably cancel the - // buffer, I guess? ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err); swapchain_result = WorstPresentResult( swapchain_result, VK_ERROR_OUT_OF_DATE_KHR); + } else { + if (img.dequeue_fence >= 0) { + close(img.dequeue_fence); + img.dequeue_fence = -1; + } + img.dequeued = false; } - if (img.dequeue_fence >= 0) { - close(img.dequeue_fence); - img.dequeue_fence = -1; - } - img.dequeued = false; // If the swapchain is in shared mode, immediately dequeue the // buffer so it can be presented again without an intervening @@ -1729,7 +1700,6 @@ VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) { } } if (swapchain_result != VK_SUCCESS) { - ReleaseSwapchainImage(device, window, fence, img); OrphanSwapchain(device, &swapchain); } int window_transform_hint; diff --git a/vulkan/nulldrv/null_driver.tmpl b/vulkan/nulldrv/null_driver.tmpl index ce155172e9..0f5301595c 100644 --- a/vulkan/nulldrv/null_driver.tmpl +++ b/vulkan/nulldrv/null_driver.tmpl @@ -97,9 +97,10 @@ VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitS ¶ // WARNING: This file is generated. See ../README.md for instructions. ¶ -#include "null_driver_gen.h" #include <algorithm> ¶ +#include "null_driver_gen.h" +¶ using namespace null_driver; ¶ namespace { diff --git a/vulkan/nulldrv/null_driver_gen.cpp b/vulkan/nulldrv/null_driver_gen.cpp index 92b7468321..b8d7d2b643 100644 --- a/vulkan/nulldrv/null_driver_gen.cpp +++ b/vulkan/nulldrv/null_driver_gen.cpp @@ -17,6 +17,7 @@ // WARNING: This file is generated. See ../README.md for instructions. #include <algorithm> + #include "null_driver_gen.h" using namespace null_driver; |