diff options
author | android-build-team Robot | 2018-02-22 02:26:32 -0600 |
---|---|---|
committer | android-build-team Robot | 2018-02-22 02:26:32 -0600 |
commit | abbf1e49f2e8fc29cc5db113c163201f8709712d (patch) | |
tree | e5dd7f99f1b70ee78a15c759596ec7b58888d5a1 | |
parent | 5fc99d0d4886b9daf423872dbd8fcafc36931ab0 (diff) | |
parent | 0dd5a5870a0431233b54867d15a26138bb17a087 (diff) | |
download | platform-hardware-interfaces-abbf1e49f2e8fc29cc5db113c163201f8709712d.tar.gz platform-hardware-interfaces-abbf1e49f2e8fc29cc5db113c163201f8709712d.tar.xz platform-hardware-interfaces-abbf1e49f2e8fc29cc5db113c163201f8709712d.zip |
Snap for 4615953 from 0dd5a5870a0431233b54867d15a26138bb17a087 to pi-release
Change-Id: I0ad9d8071b7f0d467a741607313c9d7af1be216e
70 files changed, 10198 insertions, 3827 deletions
diff --git a/authsecret/1.0/IAuthSecret.hal b/authsecret/1.0/IAuthSecret.hal index 6b573b3a..9a0fd5fd 100644 --- a/authsecret/1.0/IAuthSecret.hal +++ b/authsecret/1.0/IAuthSecret.hal | |||
@@ -42,5 +42,5 @@ interface IAuthSecret { | |||
42 | * | 42 | * |
43 | * @param secret blob derived from the primary user's credential. | 43 | * @param secret blob derived from the primary user's credential. |
44 | */ | 44 | */ |
45 | primaryUserCredential(vec<uint8_t> secret); | 45 | oneway primaryUserCredential(vec<uint8_t> secret); |
46 | }; | 46 | }; |
diff --git a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp index 57050d75..d904ad06 100644 --- a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp +++ b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp | |||
@@ -54,7 +54,7 @@ static const float kNanoToSeconds = 0.000000001f; | |||
54 | #include <android/hardware/automotive/evs/1.0/IEvsDisplay.h> | 54 | #include <android/hardware/automotive/evs/1.0/IEvsDisplay.h> |
55 | 55 | ||
56 | #include <VtsHalHidlTargetTestBase.h> | 56 | #include <VtsHalHidlTargetTestBase.h> |
57 | 57 | #include <VtsHalHidlTargetTestEnvBase.h> | |
58 | 58 | ||
59 | using namespace ::android::hardware::automotive::evs::V1_0; | 59 | using namespace ::android::hardware::automotive::evs::V1_0; |
60 | using ::android::hardware::Return; | 60 | using ::android::hardware::Return; |
@@ -64,13 +64,28 @@ using ::android::hardware::hidl_handle; | |||
64 | using ::android::hardware::hidl_string; | 64 | using ::android::hardware::hidl_string; |
65 | using ::android::sp; | 65 | using ::android::sp; |
66 | 66 | ||
67 | // Test environment for Evs HIDL HAL. | ||
68 | class EvsHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { | ||
69 | public: | ||
70 | // get the test environment singleton | ||
71 | static EvsHidlEnvironment* Instance() { | ||
72 | static EvsHidlEnvironment* instance = new EvsHidlEnvironment; | ||
73 | return instance; | ||
74 | } | ||
75 | |||
76 | virtual void registerTestServices() override { registerTestService<IEvsEnumerator>(); } | ||
77 | |||
78 | private: | ||
79 | EvsHidlEnvironment() {} | ||
80 | }; | ||
67 | 81 | ||
68 | // The main test class for EVS | 82 | // The main test class for EVS |
69 | class EvsHidlTest : public ::testing::VtsHalHidlTargetTestBase { | 83 | class EvsHidlTest : public ::testing::VtsHalHidlTargetTestBase { |
70 | public: | 84 | public: |
71 | virtual void SetUp() override { | 85 | virtual void SetUp() override { |
72 | // Make sure we can connect to the enumerator | 86 | // Make sure we can connect to the enumerator |
73 | pEnumerator = IEvsEnumerator::getService(kEnumeratorName); | 87 | pEnumerator = getService<IEvsEnumerator>( |
88 | EvsHidlEnvironment::Instance()->getServiceName<IEvsEnumerator>(kEnumeratorName)); | ||
74 | ASSERT_NE(pEnumerator.get(), nullptr); | 89 | ASSERT_NE(pEnumerator.get(), nullptr); |
75 | } | 90 | } |
76 | 91 | ||
@@ -480,3 +495,12 @@ TEST_F(EvsHidlTest, CameraToDisplayRoundTrip) { | |||
480 | // Explicitly release the display | 495 | // Explicitly release the display |
481 | pEnumerator->closeDisplay(pDisplay); | 496 | pEnumerator->closeDisplay(pDisplay); |
482 | } | 497 | } |
498 | |||
499 | int main(int argc, char** argv) { | ||
500 | ::testing::AddGlobalTestEnvironment(EvsHidlEnvironment::Instance()); | ||
501 | ::testing::InitGoogleTest(&argc, argv); | ||
502 | EvsHidlEnvironment::Instance()->init(&argc, argv); | ||
503 | int status = RUN_ALL_TESTS(); | ||
504 | ALOGI("Test result = %d", status); | ||
505 | return status; | ||
506 | } | ||
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h index 7938b731..096500e1 100644 --- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h +++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h | |||
@@ -342,12 +342,6 @@ const ConfigDeclaration kVehicleProperties[]{ | |||
342 | }, | 342 | }, |
343 | .initialValue = {.int32Values = {toInt(VehicleGear::GEAR_PARK)}}}, | 343 | .initialValue = {.int32Values = {toInt(VehicleGear::GEAR_PARK)}}}, |
344 | 344 | ||
345 | {.config = {.prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS), | ||
346 | .access = VehiclePropertyAccess::READ_WRITE, | ||
347 | .changeMode = VehiclePropertyChangeMode::ON_CHANGE, | ||
348 | .areaConfigs = {VehicleAreaConfig{.minInt32Value = 0, .maxInt32Value = 10}}}, | ||
349 | .initialValue = {.int32Values = {7}}}, | ||
350 | |||
351 | {.config = | 345 | {.config = |
352 | { | 346 | { |
353 | .prop = toInt(VehicleProperty::IGNITION_STATE), | 347 | .prop = toInt(VehicleProperty::IGNITION_STATE), |
@@ -420,6 +414,23 @@ const ConfigDeclaration kVehicleProperties[]{ | |||
420 | }, | 414 | }, |
421 | }, | 415 | }, |
422 | 416 | ||
417 | {.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE), | ||
418 | .access = VehiclePropertyAccess::READ_WRITE, | ||
419 | .changeMode = VehiclePropertyChangeMode::ON_CHANGE, | ||
420 | .configArray = {3}}, | ||
421 | .initialValue = {.int32Values = {toInt(VehicleApPowerState::ON_FULL), 0}}}, | ||
422 | |||
423 | {.config = {.prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS), | ||
424 | .access = VehiclePropertyAccess::READ_WRITE, | ||
425 | .changeMode = VehiclePropertyChangeMode::ON_CHANGE, | ||
426 | .areaConfigs = {VehicleAreaConfig{.minInt32Value = 0, .maxInt32Value = 100}}}, | ||
427 | .initialValue = {.int32Values = {100}}}, | ||
428 | |||
429 | {.config = {.prop = toInt(VehicleProperty::AP_POWER_BOOTUP_REASON), | ||
430 | .access = VehiclePropertyAccess::READ, | ||
431 | .changeMode = VehiclePropertyChangeMode::ON_CHANGE}, | ||
432 | .initialValue = {.int32Values = {toInt(VehicleApPowerBootupReason::USER_POWER_ON)}}}, | ||
433 | |||
423 | { | 434 | { |
424 | .config = {.prop = OBD2_LIVE_FRAME, | 435 | .config = {.prop = OBD2_LIVE_FRAME, |
425 | .access = VehiclePropertyAccess::READ, | 436 | .access = VehiclePropertyAccess::READ, |
diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp index b6470f5e..14f82bcf 100644 --- a/camera/device/3.4/default/ExternalCameraDevice.cpp +++ b/camera/device/3.4/default/ExternalCameraDevice.cpp | |||
@@ -131,7 +131,7 @@ Return<void> ExternalCameraDevice::open( | |||
131 | 131 | ||
132 | session = new ExternalCameraDeviceSession( | 132 | session = new ExternalCameraDeviceSession( |
133 | callback, mCfg, mSupportedFormats, mCroppingType, | 133 | callback, mCfg, mSupportedFormats, mCroppingType, |
134 | mCameraCharacteristics, std::move(fd)); | 134 | mCameraCharacteristics, mCameraId, std::move(fd)); |
135 | if (session == nullptr) { | 135 | if (session == nullptr) { |
136 | ALOGE("%s: camera device session allocation failed", __FUNCTION__); | 136 | ALOGE("%s: camera device session allocation failed", __FUNCTION__); |
137 | mLock.unlock(); | 137 | mLock.unlock(); |
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp index d6d9ff89..5346f803 100644 --- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp +++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp | |||
@@ -46,6 +46,21 @@ const int kBadFramesAfterStreamOn = 1; // drop x frames after streamOn to get ri | |||
46 | // bad frames. TODO: develop a better bad frame detection | 46 | // bad frames. TODO: develop a better bad frame detection |
47 | // method | 47 | // method |
48 | 48 | ||
49 | bool tryLock(Mutex& mutex) | ||
50 | { | ||
51 | static const int kDumpLockRetries = 50; | ||
52 | static const int kDumpLockSleep = 60000; | ||
53 | bool locked = false; | ||
54 | for (int i = 0; i < kDumpLockRetries; ++i) { | ||
55 | if (mutex.tryLock() == NO_ERROR) { | ||
56 | locked = true; | ||
57 | break; | ||
58 | } | ||
59 | usleep(kDumpLockSleep); | ||
60 | } | ||
61 | return locked; | ||
62 | } | ||
63 | |||
49 | } // Anonymous namespace | 64 | } // Anonymous namespace |
50 | 65 | ||
51 | // Static instances | 66 | // Static instances |
@@ -59,12 +74,14 @@ ExternalCameraDeviceSession::ExternalCameraDeviceSession( | |||
59 | const std::vector<SupportedV4L2Format>& sortedFormats, | 74 | const std::vector<SupportedV4L2Format>& sortedFormats, |
60 | const CroppingType& croppingType, | 75 | const CroppingType& croppingType, |
61 | const common::V1_0::helper::CameraMetadata& chars, | 76 | const common::V1_0::helper::CameraMetadata& chars, |
77 | const std::string& cameraId, | ||
62 | unique_fd v4l2Fd) : | 78 | unique_fd v4l2Fd) : |
63 | mCallback(callback), | 79 | mCallback(callback), |
64 | mCfg(cfg), | 80 | mCfg(cfg), |
65 | mCameraCharacteristics(chars), | 81 | mCameraCharacteristics(chars), |
66 | mSupportedFormats(sortedFormats), | 82 | mSupportedFormats(sortedFormats), |
67 | mCroppingType(croppingType), | 83 | mCroppingType(croppingType), |
84 | mCameraId(cameraId), | ||
68 | mV4l2Fd(std::move(v4l2Fd)), | 85 | mV4l2Fd(std::move(v4l2Fd)), |
69 | mOutputThread(new OutputThread(this, mCroppingType)), | 86 | mOutputThread(new OutputThread(this, mCroppingType)), |
70 | mMaxThumbResolution(getMaxThumbResolution()), | 87 | mMaxThumbResolution(getMaxThumbResolution()), |
@@ -119,8 +136,79 @@ ExternalCameraDeviceSession::~ExternalCameraDeviceSession() { | |||
119 | } | 136 | } |
120 | } | 137 | } |
121 | 138 | ||
122 | void ExternalCameraDeviceSession::dumpState(const native_handle_t*) { | 139 | |
123 | // TODO: b/72261676 dump more runtime information | 140 | void ExternalCameraDeviceSession::dumpState(const native_handle_t* handle) { |
141 | if (handle->numFds != 1 || handle->numInts != 0) { | ||
142 | ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints", | ||
143 | __FUNCTION__, handle->numFds, handle->numInts); | ||
144 | return; | ||
145 | } | ||
146 | int fd = handle->data[0]; | ||
147 | |||
148 | bool intfLocked = tryLock(mInterfaceLock); | ||
149 | if (!intfLocked) { | ||
150 | dprintf(fd, "!! ExternalCameraDeviceSession interface may be deadlocked !!\n"); | ||
151 | } | ||
152 | |||
153 | if (isClosed()) { | ||
154 | dprintf(fd, "External camera %s is closed\n", mCameraId.c_str()); | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | bool streaming = false; | ||
159 | size_t v4L2BufferCount = 0; | ||
160 | SupportedV4L2Format streamingFmt; | ||
161 | std::unordered_set<uint32_t> inflightFrames; | ||
162 | { | ||
163 | Mutex::Autolock _l(mLock); | ||
164 | bool sessionLocked = tryLock(mLock); | ||
165 | if (!sessionLocked) { | ||
166 | dprintf(fd, "!! ExternalCameraDeviceSession mLock may be deadlocked !!\n"); | ||
167 | } | ||
168 | streaming = mV4l2Streaming; | ||
169 | streamingFmt = mV4l2StreamingFmt; | ||
170 | v4L2BufferCount = mV4L2BufferCount; | ||
171 | inflightFrames = mInflightFrames; | ||
172 | if (sessionLocked) { | ||
173 | mLock.unlock(); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | dprintf(fd, "External camera %s V4L2 FD %d, cropping type %s, %s\n", | ||
178 | mCameraId.c_str(), mV4l2Fd.get(), | ||
179 | (mCroppingType == VERTICAL) ? "vertical" : "horizontal", | ||
180 | streaming ? "streaming" : "not streaming"); | ||
181 | if (streaming) { | ||
182 | // TODO: dump fps later | ||
183 | dprintf(fd, "Current V4L2 format %c%c%c%c %dx%d\n", | ||
184 | streamingFmt.fourcc & 0xFF, | ||
185 | (streamingFmt.fourcc >> 8) & 0xFF, | ||
186 | (streamingFmt.fourcc >> 16) & 0xFF, | ||
187 | (streamingFmt.fourcc >> 24) & 0xFF, | ||
188 | streamingFmt.width, streamingFmt.height); | ||
189 | |||
190 | size_t numDequeuedV4l2Buffers = 0; | ||
191 | { | ||
192 | std::lock_guard<std::mutex> lk(mV4l2BufferLock); | ||
193 | numDequeuedV4l2Buffers = mNumDequeuedV4l2Buffers; | ||
194 | } | ||
195 | dprintf(fd, "V4L2 buffer queue size %zu, dequeued %zu\n", | ||
196 | v4L2BufferCount, numDequeuedV4l2Buffers); | ||
197 | } | ||
198 | |||
199 | dprintf(fd, "In-flight frames (not sorted):"); | ||
200 | for (const auto& frameNumber : inflightFrames) { | ||
201 | dprintf(fd, "%d, ", frameNumber); | ||
202 | } | ||
203 | dprintf(fd, "\n"); | ||
204 | mOutputThread->dump(fd); | ||
205 | dprintf(fd, "\n"); | ||
206 | |||
207 | if (intfLocked) { | ||
208 | mInterfaceLock.unlock(); | ||
209 | } | ||
210 | |||
211 | return; | ||
124 | } | 212 | } |
125 | 213 | ||
126 | Return<void> ExternalCameraDeviceSession::constructDefaultRequestSettings( | 214 | Return<void> ExternalCameraDeviceSession::constructDefaultRequestSettings( |
@@ -281,21 +369,20 @@ Return<Status> ExternalCameraDeviceSession::flush() { | |||
281 | 369 | ||
282 | Return<void> ExternalCameraDeviceSession::close() { | 370 | Return<void> ExternalCameraDeviceSession::close() { |
283 | Mutex::Autolock _il(mInterfaceLock); | 371 | Mutex::Autolock _il(mInterfaceLock); |
284 | Mutex::Autolock _l(mLock); | 372 | bool closed = isClosed(); |
285 | if (!mClosed) { | 373 | if (!closed) { |
286 | // TODO: b/72261676 Cleanup inflight buffers/V4L2 buffer queue | 374 | mOutputThread->flush(); |
287 | ALOGV("%s: closing V4L2 camera FD %d", __FUNCTION__, mV4l2Fd.get()); | 375 | mOutputThread->requestExit(); |
288 | mV4l2Fd.reset(); | 376 | mOutputThread->join(); |
289 | mOutputThread->requestExit(); // TODO: join? | ||
290 | 377 | ||
291 | // free all imported buffers | 378 | Mutex::Autolock _l(mLock); |
292 | for(auto& pair : mCirculatingBuffers) { | 379 | // free all buffers |
293 | CirculatingBuffers& buffers = pair.second; | 380 | for(auto pair : mStreamMap) { |
294 | for (auto& p2 : buffers) { | 381 | cleanupBuffersLocked(/*Stream ID*/pair.first); |
295 | sHandleImporter.freeBuffer(p2.second); | ||
296 | } | ||
297 | } | 382 | } |
298 | 383 | v4l2StreamOffLocked(); | |
384 | ALOGV("%s: closing V4L2 camera FD %d", __FUNCTION__, mV4l2Fd.get()); | ||
385 | mV4l2Fd.reset(); | ||
299 | mClosed = true; | 386 | mClosed = true; |
300 | } | 387 | } |
301 | return Void(); | 388 | return Void(); |
@@ -431,25 +518,22 @@ Status ExternalCameraDeviceSession::processOneCaptureRequest(const CaptureReques | |||
431 | // TODO: program fps range per capture request here | 518 | // TODO: program fps range per capture request here |
432 | // or limit the set of availableFpsRange | 519 | // or limit the set of availableFpsRange |
433 | 520 | ||
434 | sp<V4L2Frame> frameIn = dequeueV4l2FrameLocked(); | 521 | |
522 | nsecs_t shutterTs = 0; | ||
523 | sp<V4L2Frame> frameIn = dequeueV4l2FrameLocked(&shutterTs); | ||
435 | if ( frameIn == nullptr) { | 524 | if ( frameIn == nullptr) { |
436 | ALOGE("%s: V4L2 deque frame failed!", __FUNCTION__); | 525 | ALOGE("%s: V4L2 deque frame failed!", __FUNCTION__); |
437 | return Status::INTERNAL_ERROR; | 526 | return Status::INTERNAL_ERROR; |
438 | } | 527 | } |
439 | // TODO: This can probably be replaced by use v4lbuffer timestamp | ||
440 | // if the device supports it | ||
441 | nsecs_t shutterTs = systemTime(SYSTEM_TIME_MONOTONIC); | ||
442 | 528 | ||
443 | 529 | std::shared_ptr<HalRequest> halReq = std::make_shared<HalRequest>(); | |
444 | // TODO: reduce object copy in this path | 530 | halReq->frameNumber = request.frameNumber; |
445 | HalRequest halReq = { | 531 | halReq->setting = mLatestReqSetting; |
446 | .frameNumber = request.frameNumber, | 532 | halReq->frameIn = frameIn; |
447 | .setting = mLatestReqSetting, | 533 | halReq->shutterTs = shutterTs; |
448 | .frameIn = frameIn, | 534 | halReq->buffers.resize(numOutputBufs); |
449 | .shutterTs = shutterTs}; | ||
450 | halReq.buffers.resize(numOutputBufs); | ||
451 | for (size_t i = 0; i < numOutputBufs; i++) { | 535 | for (size_t i = 0; i < numOutputBufs; i++) { |
452 | HalStreamBuffer& halBuf = halReq.buffers[i]; | 536 | HalStreamBuffer& halBuf = halReq->buffers[i]; |
453 | int streamId = halBuf.streamId = request.outputBuffers[i].streamId; | 537 | int streamId = halBuf.streamId = request.outputBuffers[i].streamId; |
454 | halBuf.bufferId = request.outputBuffers[i].bufferId; | 538 | halBuf.bufferId = request.outputBuffers[i].bufferId; |
455 | const Stream& stream = mStreamMap[streamId]; | 539 | const Stream& stream = mStreamMap[streamId]; |
@@ -461,7 +545,7 @@ Status ExternalCameraDeviceSession::processOneCaptureRequest(const CaptureReques | |||
461 | halBuf.acquireFence = allFences[i]; | 545 | halBuf.acquireFence = allFences[i]; |
462 | halBuf.fenceTimeout = false; | 546 | halBuf.fenceTimeout = false; |
463 | } | 547 | } |
464 | mInflightFrames.insert(halReq.frameNumber); | 548 | mInflightFrames.insert(halReq->frameNumber); |
465 | // Send request to OutputThread for the rest of processing | 549 | // Send request to OutputThread for the rest of processing |
466 | mOutputThread->submitRequest(halReq); | 550 | mOutputThread->submitRequest(halReq); |
467 | mFirstRequest = false; | 551 | mFirstRequest = false; |
@@ -487,30 +571,31 @@ void ExternalCameraDeviceSession::notifyError( | |||
487 | } | 571 | } |
488 | 572 | ||
489 | //TODO: refactor with processCaptureResult | 573 | //TODO: refactor with processCaptureResult |
490 | Status ExternalCameraDeviceSession::processCaptureRequestError(const HalRequest& req) { | 574 | Status ExternalCameraDeviceSession::processCaptureRequestError( |
575 | const std::shared_ptr<HalRequest>& req) { | ||
491 | // Return V4L2 buffer to V4L2 buffer queue | 576 | // Return V4L2 buffer to V4L2 buffer queue |
492 | enqueueV4l2Frame(req.frameIn); | 577 | enqueueV4l2Frame(req->frameIn); |
493 | 578 | ||
494 | // NotifyShutter | 579 | // NotifyShutter |
495 | notifyShutter(req.frameNumber, req.shutterTs); | 580 | notifyShutter(req->frameNumber, req->shutterTs); |
496 | 581 | ||
497 | notifyError(/*frameNum*/req.frameNumber, /*stream*/-1, ErrorCode::ERROR_REQUEST); | 582 | notifyError(/*frameNum*/req->frameNumber, /*stream*/-1, ErrorCode::ERROR_REQUEST); |
498 | 583 | ||
499 | // Fill output buffers | 584 | // Fill output buffers |
500 | hidl_vec<CaptureResult> results; | 585 | hidl_vec<CaptureResult> results; |
501 | results.resize(1); | 586 | results.resize(1); |
502 | CaptureResult& result = results[0]; | 587 | CaptureResult& result = results[0]; |
503 | result.frameNumber = req.frameNumber; | 588 | result.frameNumber = req->frameNumber; |
504 | result.partialResult = 1; | 589 | result.partialResult = 1; |
505 | result.inputBuffer.streamId = -1; | 590 | result.inputBuffer.streamId = -1; |
506 | result.outputBuffers.resize(req.buffers.size()); | 591 | result.outputBuffers.resize(req->buffers.size()); |
507 | for (size_t i = 0; i < req.buffers.size(); i++) { | 592 | for (size_t i = 0; i < req->buffers.size(); i++) { |
508 | result.outputBuffers[i].streamId = req.buffers[i].streamId; | 593 | result.outputBuffers[i].streamId = req->buffers[i].streamId; |
509 | result.outputBuffers[i].bufferId = req.buffers[i].bufferId; | 594 | result.outputBuffers[i].bufferId = req->buffers[i].bufferId; |
510 | result.outputBuffers[i].status = BufferStatus::ERROR; | 595 | result.outputBuffers[i].status = BufferStatus::ERROR; |
511 | if (req.buffers[i].acquireFence >= 0) { | 596 | if (req->buffers[i].acquireFence >= 0) { |
512 | native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0); | 597 | native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0); |
513 | handle->data[0] = req.buffers[i].acquireFence; | 598 | handle->data[0] = req->buffers[i].acquireFence; |
514 | result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false); | 599 | result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false); |
515 | } | 600 | } |
516 | } | 601 | } |
@@ -518,7 +603,7 @@ Status ExternalCameraDeviceSession::processCaptureRequestError(const HalRequest& | |||
518 | // update inflight records | 603 | // update inflight records |
519 | { | 604 | { |
520 | Mutex::Autolock _l(mLock); | 605 | Mutex::Autolock _l(mLock); |
521 | mInflightFrames.erase(req.frameNumber); | 606 | mInflightFrames.erase(req->frameNumber); |
522 | } | 607 | } |
523 | 608 | ||
524 | // Callback into framework | 609 | // Callback into framework |
@@ -527,51 +612,51 @@ Status ExternalCameraDeviceSession::processCaptureRequestError(const HalRequest& | |||
527 | return Status::OK; | 612 | return Status::OK; |
528 | } | 613 | } |
529 | 614 | ||
530 | Status ExternalCameraDeviceSession::processCaptureResult(HalRequest& req) { | 615 | Status ExternalCameraDeviceSession::processCaptureResult(std::shared_ptr<HalRequest>& req) { |
531 | // Return V4L2 buffer to V4L2 buffer queue | 616 | // Return V4L2 buffer to V4L2 buffer queue |
532 | enqueueV4l2Frame(req.frameIn); | 617 | enqueueV4l2Frame(req->frameIn); |
533 | 618 | ||
534 | // NotifyShutter | 619 | // NotifyShutter |
535 | notifyShutter(req.frameNumber, req.shutterTs); | 620 | notifyShutter(req->frameNumber, req->shutterTs); |
536 | 621 | ||
537 | // Fill output buffers | 622 | // Fill output buffers |
538 | hidl_vec<CaptureResult> results; | 623 | hidl_vec<CaptureResult> results; |
539 | results.resize(1); | 624 | results.resize(1); |
540 | CaptureResult& result = results[0]; | 625 | CaptureResult& result = results[0]; |
541 | result.frameNumber = req.frameNumber; | 626 | result.frameNumber = req->frameNumber; |
542 | result.partialResult = 1; | 627 | result.partialResult = 1; |
543 | result.inputBuffer.streamId = -1; | 628 | result.inputBuffer.streamId = -1; |
544 | result.outputBuffers.resize(req.buffers.size()); | 629 | result.outputBuffers.resize(req->buffers.size()); |
545 | for (size_t i = 0; i < req.buffers.size(); i++) { | 630 | for (size_t i = 0; i < req->buffers.size(); i++) { |
546 | result.outputBuffers[i].streamId = req.buffers[i].streamId; | 631 | result.outputBuffers[i].streamId = req->buffers[i].streamId; |
547 | result.outputBuffers[i].bufferId = req.buffers[i].bufferId; | 632 | result.outputBuffers[i].bufferId = req->buffers[i].bufferId; |
548 | if (req.buffers[i].fenceTimeout) { | 633 | if (req->buffers[i].fenceTimeout) { |
549 | result.outputBuffers[i].status = BufferStatus::ERROR; | 634 | result.outputBuffers[i].status = BufferStatus::ERROR; |
550 | native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0); | 635 | native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0); |
551 | handle->data[0] = req.buffers[i].acquireFence; | 636 | handle->data[0] = req->buffers[i].acquireFence; |
552 | result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false); | 637 | result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false); |
553 | notifyError(req.frameNumber, req.buffers[i].streamId, ErrorCode::ERROR_BUFFER); | 638 | notifyError(req->frameNumber, req->buffers[i].streamId, ErrorCode::ERROR_BUFFER); |
554 | } else { | 639 | } else { |
555 | result.outputBuffers[i].status = BufferStatus::OK; | 640 | result.outputBuffers[i].status = BufferStatus::OK; |
556 | // TODO: refactor | 641 | // TODO: refactor |
557 | if (req.buffers[i].acquireFence > 0) { | 642 | if (req->buffers[i].acquireFence > 0) { |
558 | native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0); | 643 | native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0); |
559 | handle->data[0] = req.buffers[i].acquireFence; | 644 | handle->data[0] = req->buffers[i].acquireFence; |
560 | result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false); | 645 | result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false); |
561 | } | 646 | } |
562 | } | 647 | } |
563 | } | 648 | } |
564 | 649 | ||
565 | // Fill capture result metadata | 650 | // Fill capture result metadata |
566 | fillCaptureResult(req.setting, req.shutterTs); | 651 | fillCaptureResult(req->setting, req->shutterTs); |
567 | const camera_metadata_t *rawResult = req.setting.getAndLock(); | 652 | const camera_metadata_t *rawResult = req->setting.getAndLock(); |
568 | V3_2::implementation::convertToHidl(rawResult, &result.result); | 653 | V3_2::implementation::convertToHidl(rawResult, &result.result); |
569 | req.setting.unlock(rawResult); | 654 | req->setting.unlock(rawResult); |
570 | 655 | ||
571 | // update inflight records | 656 | // update inflight records |
572 | { | 657 | { |
573 | Mutex::Autolock _l(mLock); | 658 | Mutex::Autolock _l(mLock); |
574 | mInflightFrames.erase(req.frameNumber); | 659 | mInflightFrames.erase(req->frameNumber); |
575 | } | 660 | } |
576 | 661 | ||
577 | // Callback into framework | 662 | // Callback into framework |
@@ -1302,7 +1387,7 @@ ssize_t ExternalCameraDeviceSession::getJpegBufferSize( | |||
1302 | 1387 | ||
1303 | int ExternalCameraDeviceSession::OutputThread::createJpegLocked( | 1388 | int ExternalCameraDeviceSession::OutputThread::createJpegLocked( |
1304 | HalStreamBuffer &halBuf, | 1389 | HalStreamBuffer &halBuf, |
1305 | HalRequest &req) | 1390 | const std::shared_ptr<HalRequest>& req) |
1306 | { | 1391 | { |
1307 | int ret; | 1392 | int ret; |
1308 | auto lfail = [&](auto... args) { | 1393 | auto lfail = [&](auto... args) { |
@@ -1329,17 +1414,17 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked( | |||
1329 | int jpegQuality, thumbQuality; | 1414 | int jpegQuality, thumbQuality; |
1330 | Size thumbSize; | 1415 | Size thumbSize; |
1331 | 1416 | ||
1332 | if (req.setting.exists(ANDROID_JPEG_QUALITY)) { | 1417 | if (req->setting.exists(ANDROID_JPEG_QUALITY)) { |
1333 | camera_metadata_entry entry = | 1418 | camera_metadata_entry entry = |
1334 | req.setting.find(ANDROID_JPEG_QUALITY); | 1419 | req->setting.find(ANDROID_JPEG_QUALITY); |
1335 | jpegQuality = entry.data.u8[0]; | 1420 | jpegQuality = entry.data.u8[0]; |
1336 | } else { | 1421 | } else { |
1337 | return lfail("%s: ANDROID_JPEG_QUALITY not set",__FUNCTION__); | 1422 | return lfail("%s: ANDROID_JPEG_QUALITY not set",__FUNCTION__); |
1338 | } | 1423 | } |
1339 | 1424 | ||
1340 | if (req.setting.exists(ANDROID_JPEG_THUMBNAIL_QUALITY)) { | 1425 | if (req->setting.exists(ANDROID_JPEG_THUMBNAIL_QUALITY)) { |
1341 | camera_metadata_entry entry = | 1426 | camera_metadata_entry entry = |
1342 | req.setting.find(ANDROID_JPEG_THUMBNAIL_QUALITY); | 1427 | req->setting.find(ANDROID_JPEG_THUMBNAIL_QUALITY); |
1343 | thumbQuality = entry.data.u8[0]; | 1428 | thumbQuality = entry.data.u8[0]; |
1344 | } else { | 1429 | } else { |
1345 | return lfail( | 1430 | return lfail( |
@@ -1347,9 +1432,9 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked( | |||
1347 | __FUNCTION__); | 1432 | __FUNCTION__); |
1348 | } | 1433 | } |
1349 | 1434 | ||
1350 | if (req.setting.exists(ANDROID_JPEG_THUMBNAIL_SIZE)) { | 1435 | if (req->setting.exists(ANDROID_JPEG_THUMBNAIL_SIZE)) { |
1351 | camera_metadata_entry entry = | 1436 | camera_metadata_entry entry = |
1352 | req.setting.find(ANDROID_JPEG_THUMBNAIL_SIZE); | 1437 | req->setting.find(ANDROID_JPEG_THUMBNAIL_SIZE); |
1353 | thumbSize = Size { static_cast<uint32_t>(entry.data.i32[0]), | 1438 | thumbSize = Size { static_cast<uint32_t>(entry.data.i32[0]), |
1354 | static_cast<uint32_t>(entry.data.i32[1]) | 1439 | static_cast<uint32_t>(entry.data.i32[1]) |
1355 | }; | 1440 | }; |
@@ -1409,7 +1494,7 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked( | |||
1409 | /* Combine camera characteristics with request settings to form EXIF | 1494 | /* Combine camera characteristics with request settings to form EXIF |
1410 | * metadata */ | 1495 | * metadata */ |
1411 | common::V1_0::helper::CameraMetadata meta(parent->mCameraCharacteristics); | 1496 | common::V1_0::helper::CameraMetadata meta(parent->mCameraCharacteristics); |
1412 | meta.append(req.setting); | 1497 | meta.append(req->setting); |
1413 | 1498 | ||
1414 | /* Generate EXIF object */ | 1499 | /* Generate EXIF object */ |
1415 | std::unique_ptr<ExifUtils> utils(ExifUtils::create()); | 1500 | std::unique_ptr<ExifUtils> utils(ExifUtils::create()); |
@@ -1473,7 +1558,7 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked( | |||
1473 | } | 1558 | } |
1474 | 1559 | ||
1475 | bool ExternalCameraDeviceSession::OutputThread::threadLoop() { | 1560 | bool ExternalCameraDeviceSession::OutputThread::threadLoop() { |
1476 | HalRequest req; | 1561 | std::shared_ptr<HalRequest> req; |
1477 | auto parent = mParent.promote(); | 1562 | auto parent = mParent.promote(); |
1478 | if (parent == nullptr) { | 1563 | if (parent == nullptr) { |
1479 | ALOGE("%s: session has been disconnected!", __FUNCTION__); | 1564 | ALOGE("%s: session has been disconnected!", __FUNCTION__); |
@@ -1484,7 +1569,7 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() { | |||
1484 | // regularly to prevent v4l buffer queue filled with stale buffers | 1569 | // regularly to prevent v4l buffer queue filled with stale buffers |
1485 | // when app doesn't program a preveiw request | 1570 | // when app doesn't program a preveiw request |
1486 | waitForNextRequest(&req); | 1571 | waitForNextRequest(&req); |
1487 | if (req.frameIn == nullptr) { | 1572 | if (req == nullptr) { |
1488 | // No new request, wait again | 1573 | // No new request, wait again |
1489 | return true; | 1574 | return true; |
1490 | } | 1575 | } |
@@ -1492,17 +1577,17 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() { | |||
1492 | auto onDeviceError = [&](auto... args) { | 1577 | auto onDeviceError = [&](auto... args) { |
1493 | ALOGE(args...); | 1578 | ALOGE(args...); |
1494 | parent->notifyError( | 1579 | parent->notifyError( |
1495 | req.frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE); | 1580 | req->frameNumber, /*stream*/-1, ErrorCode::ERROR_DEVICE); |
1496 | signalRequestDone(); | 1581 | signalRequestDone(); |
1497 | return false; | 1582 | return false; |
1498 | }; | 1583 | }; |
1499 | 1584 | ||
1500 | if (req.frameIn->mFourcc != V4L2_PIX_FMT_MJPEG) { | 1585 | if (req->frameIn->mFourcc != V4L2_PIX_FMT_MJPEG) { |
1501 | return onDeviceError("%s: do not support V4L2 format %c%c%c%c", __FUNCTION__, | 1586 | return onDeviceError("%s: do not support V4L2 format %c%c%c%c", __FUNCTION__, |
1502 | req.frameIn->mFourcc & 0xFF, | 1587 | req->frameIn->mFourcc & 0xFF, |
1503 | (req.frameIn->mFourcc >> 8) & 0xFF, | 1588 | (req->frameIn->mFourcc >> 8) & 0xFF, |
1504 | (req.frameIn->mFourcc >> 16) & 0xFF, | 1589 | (req->frameIn->mFourcc >> 16) & 0xFF, |
1505 | (req.frameIn->mFourcc >> 24) & 0xFF); | 1590 | (req->frameIn->mFourcc >> 24) & 0xFF); |
1506 | } | 1591 | } |
1507 | 1592 | ||
1508 | std::unique_lock<std::mutex> lk(mBufferLock); | 1593 | std::unique_lock<std::mutex> lk(mBufferLock); |
@@ -1510,7 +1595,7 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() { | |||
1510 | // TODO: see if we can save some computation by converting to YV12 here | 1595 | // TODO: see if we can save some computation by converting to YV12 here |
1511 | uint8_t* inData; | 1596 | uint8_t* inData; |
1512 | size_t inDataSize; | 1597 | size_t inDataSize; |
1513 | req.frameIn->map(&inData, &inDataSize); | 1598 | req->frameIn->map(&inData, &inDataSize); |
1514 | // TODO: profile | 1599 | // TODO: profile |
1515 | // TODO: in some special case maybe we can decode jpg directly to gralloc output? | 1600 | // TODO: in some special case maybe we can decode jpg directly to gralloc output? |
1516 | int res = libyuv::MJPGToI420( | 1601 | int res = libyuv::MJPGToI420( |
@@ -1538,7 +1623,7 @@ bool ExternalCameraDeviceSession::OutputThread::threadLoop() { | |||
1538 | 1623 | ||
1539 | ALOGV("%s processing new request", __FUNCTION__); | 1624 | ALOGV("%s processing new request", __FUNCTION__); |
1540 | const int kSyncWaitTimeoutMs = 500; | 1625 | const int kSyncWaitTimeoutMs = 500; |
1541 | for (auto& halBuf : req.buffers) { | 1626 | for (auto& halBuf : req->buffers) { |
1542 | if (halBuf.acquireFence != -1) { | 1627 | if (halBuf.acquireFence != -1) { |
1543 | int ret = sync_wait(halBuf.acquireFence, kSyncWaitTimeoutMs); | 1628 | int ret = sync_wait(halBuf.acquireFence, kSyncWaitTimeoutMs); |
1544 | if (ret) { | 1629 | if (ret) { |
@@ -1695,9 +1780,9 @@ Status ExternalCameraDeviceSession::OutputThread::allocateIntermediateBuffers( | |||
1695 | return Status::OK; | 1780 | return Status::OK; |
1696 | } | 1781 | } |
1697 | 1782 | ||
1698 | Status ExternalCameraDeviceSession::OutputThread::submitRequest(const HalRequest& req) { | 1783 | Status ExternalCameraDeviceSession::OutputThread::submitRequest( |
1784 | const std::shared_ptr<HalRequest>& req) { | ||
1699 | std::unique_lock<std::mutex> lk(mRequestListLock); | 1785 | std::unique_lock<std::mutex> lk(mRequestListLock); |
1700 | // TODO: reduce object copy in this path | ||
1701 | mRequestList.push_back(req); | 1786 | mRequestList.push_back(req); |
1702 | lk.unlock(); | 1787 | lk.unlock(); |
1703 | mRequestCond.notify_one(); | 1788 | mRequestCond.notify_one(); |
@@ -1712,10 +1797,10 @@ void ExternalCameraDeviceSession::OutputThread::flush() { | |||
1712 | } | 1797 | } |
1713 | 1798 | ||
1714 | std::unique_lock<std::mutex> lk(mRequestListLock); | 1799 | std::unique_lock<std::mutex> lk(mRequestListLock); |
1715 | std::list<HalRequest> reqs = mRequestList; | 1800 | std::list<std::shared_ptr<HalRequest>> reqs = std::move(mRequestList); |
1716 | mRequestList.clear(); | 1801 | mRequestList.clear(); |
1717 | if (mProcessingRequest) { | 1802 | if (mProcessingRequest) { |
1718 | std::chrono::seconds timeout = std::chrono::seconds(kReqWaitTimeoutSec); | 1803 | std::chrono::seconds timeout = std::chrono::seconds(kFlushWaitTimeoutSec); |
1719 | auto st = mRequestDoneCond.wait_for(lk, timeout); | 1804 | auto st = mRequestDoneCond.wait_for(lk, timeout); |
1720 | if (st == std::cv_status::timeout) { | 1805 | if (st == std::cv_status::timeout) { |
1721 | ALOGE("%s: wait for inflight request finish timeout!", __FUNCTION__); | 1806 | ALOGE("%s: wait for inflight request finish timeout!", __FUNCTION__); |
@@ -1728,33 +1813,57 @@ void ExternalCameraDeviceSession::OutputThread::flush() { | |||
1728 | } | 1813 | } |
1729 | } | 1814 | } |
1730 | 1815 | ||
1731 | void ExternalCameraDeviceSession::OutputThread::waitForNextRequest(HalRequest* out) { | 1816 | void ExternalCameraDeviceSession::OutputThread::waitForNextRequest( |
1817 | std::shared_ptr<HalRequest>* out) { | ||
1732 | if (out == nullptr) { | 1818 | if (out == nullptr) { |
1733 | ALOGE("%s: out is null", __FUNCTION__); | 1819 | ALOGE("%s: out is null", __FUNCTION__); |
1734 | return; | 1820 | return; |
1735 | } | 1821 | } |
1736 | 1822 | ||
1737 | std::unique_lock<std::mutex> lk(mRequestListLock); | 1823 | std::unique_lock<std::mutex> lk(mRequestListLock); |
1824 | int waitTimes = 0; | ||
1738 | while (mRequestList.empty()) { | 1825 | while (mRequestList.empty()) { |
1739 | std::chrono::seconds timeout = std::chrono::seconds(kReqWaitTimeoutSec); | 1826 | if (exitPending()) { |
1827 | return; | ||
1828 | } | ||
1829 | std::chrono::milliseconds timeout = std::chrono::milliseconds(kReqWaitTimeoutMs); | ||
1740 | auto st = mRequestCond.wait_for(lk, timeout); | 1830 | auto st = mRequestCond.wait_for(lk, timeout); |
1741 | if (st == std::cv_status::timeout) { | 1831 | if (st == std::cv_status::timeout) { |
1742 | // no new request, return | 1832 | waitTimes++; |
1743 | return; | 1833 | if (waitTimes == kReqWaitTimesMax) { |
1834 | // no new request, return | ||
1835 | return; | ||
1836 | } | ||
1744 | } | 1837 | } |
1745 | } | 1838 | } |
1746 | *out = mRequestList.front(); | 1839 | *out = mRequestList.front(); |
1747 | mRequestList.pop_front(); | 1840 | mRequestList.pop_front(); |
1748 | mProcessingRequest = true; | 1841 | mProcessingRequest = true; |
1842 | mProcessingFrameNumer = (*out)->frameNumber; | ||
1749 | } | 1843 | } |
1750 | 1844 | ||
1751 | void ExternalCameraDeviceSession::OutputThread::signalRequestDone() { | 1845 | void ExternalCameraDeviceSession::OutputThread::signalRequestDone() { |
1752 | std::unique_lock<std::mutex> lk(mRequestListLock); | 1846 | std::unique_lock<std::mutex> lk(mRequestListLock); |
1753 | mProcessingRequest = false; | 1847 | mProcessingRequest = false; |
1848 | mProcessingFrameNumer = 0; | ||
1754 | lk.unlock(); | 1849 | lk.unlock(); |
1755 | mRequestDoneCond.notify_one(); | 1850 | mRequestDoneCond.notify_one(); |
1756 | } | 1851 | } |
1757 | 1852 | ||
1853 | void ExternalCameraDeviceSession::OutputThread::dump(int fd) { | ||
1854 | std::lock_guard<std::mutex> lk(mRequestListLock); | ||
1855 | if (mProcessingRequest) { | ||
1856 | dprintf(fd, "OutputThread processing frame %d\n", mProcessingFrameNumer); | ||
1857 | } else { | ||
1858 | dprintf(fd, "OutputThread not processing any frames\n"); | ||
1859 | } | ||
1860 | dprintf(fd, "OutputThread request list contains frame: "); | ||
1861 | for (const auto& req : mRequestList) { | ||
1862 | dprintf(fd, "%d, ", req->frameNumber); | ||
1863 | } | ||
1864 | dprintf(fd, "\n"); | ||
1865 | } | ||
1866 | |||
1758 | void ExternalCameraDeviceSession::cleanupBuffersLocked(int id) { | 1867 | void ExternalCameraDeviceSession::cleanupBuffersLocked(int id) { |
1759 | for (auto& pair : mCirculatingBuffers.at(id)) { | 1868 | for (auto& pair : mCirculatingBuffers.at(id)) { |
1760 | sHandleImporter.freeBuffer(pair.second); | 1869 | sHandleImporter.freeBuffer(pair.second); |
@@ -2016,15 +2125,25 @@ int ExternalCameraDeviceSession::configureV4l2StreamLocked(const SupportedV4L2Fo | |||
2016 | return OK; | 2125 | return OK; |
2017 | } | 2126 | } |
2018 | 2127 | ||
2019 | sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked() { | 2128 | sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked(/*out*/nsecs_t* shutterTs) { |
2020 | sp<V4L2Frame> ret = nullptr; | 2129 | sp<V4L2Frame> ret = nullptr; |
2021 | 2130 | ||
2131 | if (shutterTs == nullptr) { | ||
2132 | ALOGE("%s: shutterTs must not be null!", __FUNCTION__); | ||
2133 | return ret; | ||
2134 | } | ||
2135 | |||
2022 | { | 2136 | { |
2023 | std::unique_lock<std::mutex> lk(mV4l2BufferLock); | 2137 | std::unique_lock<std::mutex> lk(mV4l2BufferLock); |
2024 | if (mNumDequeuedV4l2Buffers == mV4L2BufferCount) { | 2138 | if (mNumDequeuedV4l2Buffers == mV4L2BufferCount) { |
2025 | std::chrono::seconds timeout = std::chrono::seconds(kBufferWaitTimeoutSec); | 2139 | std::chrono::seconds timeout = std::chrono::seconds(kBufferWaitTimeoutSec); |
2026 | mLock.unlock(); | 2140 | mLock.unlock(); |
2027 | auto st = mV4L2BufferReturned.wait_for(lk, timeout); | 2141 | auto st = mV4L2BufferReturned.wait_for(lk, timeout); |
2142 | // Here we introduce a case where mV4l2BufferLock is acquired before mLock, while | ||
2143 | // the normal lock acquisition order is reversed, but this is fine because in most of | ||
2144 | // cases we are protected by mInterfaceLock. The only thread that can compete these | ||
2145 | // locks are the OutputThread, where we do need to make sure we don't acquire mLock then | ||
2146 | // mV4l2BufferLock | ||
2028 | mLock.lock(); | 2147 | mLock.lock(); |
2029 | if (st == std::cv_status::timeout) { | 2148 | if (st == std::cv_status::timeout) { |
2030 | ALOGE("%s: wait for V4L2 buffer return timeout!", __FUNCTION__); | 2149 | ALOGE("%s: wait for V4L2 buffer return timeout!", __FUNCTION__); |
@@ -2051,6 +2170,15 @@ sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked() { | |||
2051 | // TODO: try to dequeue again | 2170 | // TODO: try to dequeue again |
2052 | } | 2171 | } |
2053 | 2172 | ||
2173 | if (buffer.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC) { | ||
2174 | // Ideally we should also check for V4L2_BUF_FLAG_TSTAMP_SRC_SOE, but | ||
2175 | // even V4L2_BUF_FLAG_TSTAMP_SRC_EOF is better than capture a timestamp now | ||
2176 | *shutterTs = static_cast<nsecs_t>(buffer.timestamp.tv_sec)*1000000000LL + | ||
2177 | buffer.timestamp.tv_usec * 1000LL; | ||
2178 | } else { | ||
2179 | *shutterTs = systemTime(SYSTEM_TIME_MONOTONIC); | ||
2180 | } | ||
2181 | |||
2054 | { | 2182 | { |
2055 | std::lock_guard<std::mutex> lk(mV4l2BufferLock); | 2183 | std::lock_guard<std::mutex> lk(mV4l2BufferLock); |
2056 | mNumDequeuedV4l2Buffers++; | 2184 | mNumDequeuedV4l2Buffers++; |
@@ -2061,15 +2189,20 @@ sp<V4L2Frame> ExternalCameraDeviceSession::dequeueV4l2FrameLocked() { | |||
2061 | } | 2189 | } |
2062 | 2190 | ||
2063 | void ExternalCameraDeviceSession::enqueueV4l2Frame(const sp<V4L2Frame>& frame) { | 2191 | void ExternalCameraDeviceSession::enqueueV4l2Frame(const sp<V4L2Frame>& frame) { |
2064 | Mutex::Autolock _l(mLock); | 2192 | { |
2065 | frame->unmap(); | 2193 | // Release mLock before acquiring mV4l2BufferLock to avoid potential |
2066 | v4l2_buffer buffer{}; | 2194 | // deadlock |
2067 | buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 2195 | Mutex::Autolock _l(mLock); |
2068 | buffer.memory = V4L2_MEMORY_MMAP; | 2196 | frame->unmap(); |
2069 | buffer.index = frame->mBufferIndex; | 2197 | v4l2_buffer buffer{}; |
2070 | if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer)) < 0) { | 2198 | buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
2071 | ALOGE("%s: QBUF index %d fails: %s", __FUNCTION__, frame->mBufferIndex, strerror(errno)); | 2199 | buffer.memory = V4L2_MEMORY_MMAP; |
2072 | return; | 2200 | buffer.index = frame->mBufferIndex; |
2201 | if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_QBUF, &buffer)) < 0) { | ||
2202 | ALOGE("%s: QBUF index %d fails: %s", __FUNCTION__, | ||
2203 | frame->mBufferIndex, strerror(errno)); | ||
2204 | return; | ||
2205 | } | ||
2073 | } | 2206 | } |
2074 | 2207 | ||
2075 | { | 2208 | { |
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h index 43656c84..9c0ad7f5 100644 --- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h +++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h | |||
@@ -91,6 +91,7 @@ struct ExternalCameraDeviceSession : public virtual RefBase { | |||
91 | const std::vector<SupportedV4L2Format>& sortedFormats, | 91 | const std::vector<SupportedV4L2Format>& sortedFormats, |
92 | const CroppingType& croppingType, | 92 | const CroppingType& croppingType, |
93 | const common::V1_0::helper::CameraMetadata& chars, | 93 | const common::V1_0::helper::CameraMetadata& chars, |
94 | const std::string& cameraId, | ||
94 | unique_fd v4l2Fd); | 95 | unique_fd v4l2Fd); |
95 | virtual ~ExternalCameraDeviceSession(); | 96 | virtual ~ExternalCameraDeviceSession(); |
96 | // Call by CameraDevice to dump active device states | 97 | // Call by CameraDevice to dump active device states |
@@ -180,7 +181,7 @@ protected: | |||
180 | int v4l2StreamOffLocked(); | 181 | int v4l2StreamOffLocked(); |
181 | 182 | ||
182 | // TODO: change to unique_ptr for better tracking | 183 | // TODO: change to unique_ptr for better tracking |
183 | sp<V4L2Frame> dequeueV4l2FrameLocked(); // Called with mLock hold | 184 | sp<V4L2Frame> dequeueV4l2FrameLocked(/*out*/nsecs_t* shutterTs); // Called with mLock hold |
184 | void enqueueV4l2Frame(const sp<V4L2Frame>&); | 185 | void enqueueV4l2Frame(const sp<V4L2Frame>&); |
185 | 186 | ||
186 | // Check if input Stream is one of supported stream setting on this device | 187 | // Check if input Stream is one of supported stream setting on this device |
@@ -198,8 +199,8 @@ protected: | |||
198 | 199 | ||
199 | Status processOneCaptureRequest(const CaptureRequest& request); | 200 | Status processOneCaptureRequest(const CaptureRequest& request); |
200 | 201 | ||
201 | Status processCaptureResult(HalRequest&); | 202 | Status processCaptureResult(std::shared_ptr<HalRequest>&); |
202 | Status processCaptureRequestError(const HalRequest&); | 203 | Status processCaptureRequestError(const std::shared_ptr<HalRequest>&); |
203 | void notifyShutter(uint32_t frameNumber, nsecs_t shutterTs); | 204 | void notifyShutter(uint32_t frameNumber, nsecs_t shutterTs); |
204 | void notifyError(uint32_t frameNumber, int32_t streamId, ErrorCode ec); | 205 | void notifyError(uint32_t frameNumber, int32_t streamId, ErrorCode ec); |
205 | void invokeProcessCaptureResultCallback( | 206 | void invokeProcessCaptureResultCallback( |
@@ -219,8 +220,9 @@ protected: | |||
219 | Status allocateIntermediateBuffers( | 220 | Status allocateIntermediateBuffers( |
220 | const Size& v4lSize, const Size& thumbSize, | 221 | const Size& v4lSize, const Size& thumbSize, |
221 | const hidl_vec<Stream>& streams); | 222 | const hidl_vec<Stream>& streams); |
222 | Status submitRequest(const HalRequest&); | 223 | Status submitRequest(const std::shared_ptr<HalRequest>&); |
223 | void flush(); | 224 | void flush(); |
225 | void dump(int fd); | ||
224 | virtual bool threadLoop() override; | 226 | virtual bool threadLoop() override; |
225 | 227 | ||
226 | private: | 228 | private: |
@@ -232,9 +234,11 @@ protected: | |||
232 | static int getCropRect( | 234 | static int getCropRect( |
233 | CroppingType ct, const Size& inSize, const Size& outSize, IMapper::Rect* out); | 235 | CroppingType ct, const Size& inSize, const Size& outSize, IMapper::Rect* out); |
234 | 236 | ||
235 | static const int kReqWaitTimeoutSec = 3; | 237 | static const int kFlushWaitTimeoutSec = 3; // 3 sec |
238 | static const int kReqWaitTimeoutMs = 33; // 33ms | ||
239 | static const int kReqWaitTimesMax = 90; // 33ms * 90 ~= 3 sec | ||
236 | 240 | ||
237 | void waitForNextRequest(HalRequest* out); | 241 | void waitForNextRequest(std::shared_ptr<HalRequest>* out); |
238 | void signalRequestDone(); | 242 | void signalRequestDone(); |
239 | 243 | ||
240 | int cropAndScaleLocked( | 244 | int cropAndScaleLocked( |
@@ -254,16 +258,18 @@ protected: | |||
254 | void *out, size_t maxOutSize, | 258 | void *out, size_t maxOutSize, |
255 | size_t &actualCodeSize); | 259 | size_t &actualCodeSize); |
256 | 260 | ||
257 | int createJpegLocked(HalStreamBuffer &halBuf, HalRequest &req); | 261 | int createJpegLocked(HalStreamBuffer &halBuf, const std::shared_ptr<HalRequest>& req); |
258 | 262 | ||
259 | const wp<ExternalCameraDeviceSession> mParent; | 263 | const wp<ExternalCameraDeviceSession> mParent; |
260 | const CroppingType mCroppingType; | 264 | const CroppingType mCroppingType; |
261 | 265 | ||
262 | mutable std::mutex mRequestListLock; // Protect acccess to mRequestList | 266 | mutable std::mutex mRequestListLock; // Protect acccess to mRequestList, |
267 | // mProcessingRequest and mProcessingFrameNumer | ||
263 | std::condition_variable mRequestCond; // signaled when a new request is submitted | 268 | std::condition_variable mRequestCond; // signaled when a new request is submitted |
264 | std::condition_variable mRequestDoneCond; // signaled when a request is done processing | 269 | std::condition_variable mRequestDoneCond; // signaled when a request is done processing |
265 | std::list<HalRequest> mRequestList; | 270 | std::list<std::shared_ptr<HalRequest>> mRequestList; |
266 | bool mProcessingRequest = false; | 271 | bool mProcessingRequest = false; |
272 | uint32_t mProcessingFrameNumer = 0; | ||
267 | 273 | ||
268 | // V4L2 frameIn | 274 | // V4L2 frameIn |
269 | // (MJPG decode)-> mYu12Frame | 275 | // (MJPG decode)-> mYu12Frame |
@@ -287,7 +293,9 @@ protected: | |||
287 | const common::V1_0::helper::CameraMetadata mCameraCharacteristics; | 293 | const common::V1_0::helper::CameraMetadata mCameraCharacteristics; |
288 | const std::vector<SupportedV4L2Format> mSupportedFormats; | 294 | const std::vector<SupportedV4L2Format> mSupportedFormats; |
289 | const CroppingType mCroppingType; | 295 | const CroppingType mCroppingType; |
296 | const std::string& mCameraId; | ||
290 | unique_fd mV4l2Fd; | 297 | unique_fd mV4l2Fd; |
298 | |||
291 | // device is closed either | 299 | // device is closed either |
292 | // - closed by user | 300 | // - closed by user |
293 | // - init failed | 301 | // - init failed |
diff --git a/confirmationui/1.0/vts/OWNERS b/confirmationui/1.0/vts/OWNERS new file mode 100644 index 00000000..e7aa8b4b --- /dev/null +++ b/confirmationui/1.0/vts/OWNERS | |||
@@ -0,0 +1,3 @@ | |||
1 | jdanis@google.com | ||
2 | swillden@google.com | ||
3 | yim@google.com | ||
diff --git a/confirmationui/1.0/vts/functional/Android.bp b/confirmationui/1.0/vts/functional/Android.bp new file mode 100644 index 00000000..823e035a --- /dev/null +++ b/confirmationui/1.0/vts/functional/Android.bp | |||
@@ -0,0 +1,30 @@ | |||
1 | // | ||
2 | // Copyright (C) 2018 The Android Open Source Project | ||
3 | // | ||
4 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | // you may not use this file except in compliance with the License. | ||
6 | // You may obtain a copy of the License at | ||
7 | // | ||
8 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | // | ||
10 | // Unless required by applicable law or agreed to in writing, software | ||
11 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | // See the License for the specific language governing permissions and | ||
14 | // limitations under the License. | ||
15 | // | ||
16 | |||
17 | cc_test { | ||
18 | name: "VtsHalConfirmationUIV1_0TargetTest", | ||
19 | defaults: ["VtsHalTargetTestDefaults"], | ||
20 | srcs: [ | ||
21 | "VtsHalConfirmationUIV1_0TargetTest.cpp", | ||
22 | ], | ||
23 | static_libs: [ | ||
24 | "android.hardware.confirmationui@1.0", | ||
25 | "android.hardware.keymaster@4.0", | ||
26 | "libcrypto", | ||
27 | "libcn-cbor", | ||
28 | "android.hardware.confirmationui-support-lib", | ||
29 | ], | ||
30 | } | ||
diff --git a/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp b/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp new file mode 100644 index 00000000..463bb40a --- /dev/null +++ b/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp | |||
@@ -0,0 +1,428 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #define LOG_TAG "ConfirmationIOHidlHalTest" | ||
18 | #include <cutils/log.h> | ||
19 | |||
20 | #include <algorithm> | ||
21 | #include <iostream> | ||
22 | #include <memory> | ||
23 | |||
24 | #include <android/hardware/confirmationui/1.0/IConfirmationResultCallback.h> | ||
25 | #include <android/hardware/confirmationui/1.0/IConfirmationUI.h> | ||
26 | #include <android/hardware/confirmationui/1.0/types.h> | ||
27 | #include <android/hardware/confirmationui/support/confirmationui_utils.h> | ||
28 | |||
29 | #include <VtsHalHidlTargetCallbackBase.h> | ||
30 | #include <VtsHalHidlTargetTestBase.h> | ||
31 | |||
32 | #include <openssl/hmac.h> | ||
33 | #include <openssl/sha.h> | ||
34 | |||
35 | #include <cn-cbor/cn-cbor.h> | ||
36 | |||
37 | using ::android::sp; | ||
38 | |||
39 | using ::std::string; | ||
40 | |||
41 | namespace android { | ||
42 | namespace hardware { | ||
43 | |||
44 | namespace confirmationui { | ||
45 | namespace V1_0 { | ||
46 | |||
47 | namespace test { | ||
48 | namespace { | ||
49 | class HMacImplementation { | ||
50 | public: | ||
51 | static support::NullOr<support::array<uint8_t, 32>> hmac256( | ||
52 | const uint8_t key[32], std::initializer_list<support::ByteBufferProxy> buffers) { | ||
53 | HMAC_CTX hmacCtx; | ||
54 | HMAC_CTX_init(&hmacCtx); | ||
55 | if (!HMAC_Init_ex(&hmacCtx, key, 32, EVP_sha256(), nullptr)) { | ||
56 | return {}; | ||
57 | } | ||
58 | for (auto& buffer : buffers) { | ||
59 | if (!HMAC_Update(&hmacCtx, buffer.data(), buffer.size())) { | ||
60 | return {}; | ||
61 | } | ||
62 | } | ||
63 | support::array<uint8_t, 32> result; | ||
64 | if (!HMAC_Final(&hmacCtx, result.data(), nullptr)) { | ||
65 | return {}; | ||
66 | } | ||
67 | return result; | ||
68 | } | ||
69 | }; | ||
70 | |||
71 | using HMacer = support::HMac<HMacImplementation>; | ||
72 | |||
73 | constexpr uint8_t testKeyByte = static_cast<uint8_t>(TestKeyBits::BYTE); | ||
74 | |||
75 | template <typename... Data> | ||
76 | hidl_vec<uint8_t> testHMAC(const Data&... data) { | ||
77 | constexpr uint8_t testKey[32] = {testKeyByte, testKeyByte, testKeyByte, testKeyByte, | ||
78 | testKeyByte, testKeyByte, testKeyByte, testKeyByte, | ||
79 | testKeyByte, testKeyByte, testKeyByte, testKeyByte, | ||
80 | testKeyByte, testKeyByte, testKeyByte, testKeyByte}; | ||
81 | constexpr uint8_t hmac_size_bytes = sizeof testKey; | ||
82 | |||
83 | auto hmac = HMacer::hmac256(testKey, data...); | ||
84 | if (!hmac.isOk()) { | ||
85 | EXPECT_TRUE(false) << "Failed to compute test hmac. This is a self-test error."; | ||
86 | return {}; | ||
87 | } | ||
88 | hidl_vec<uint8_t> result(hmac_size_bytes); | ||
89 | copy(hmac.value().data(), hmac.value().data() + hmac_size_bytes, result.data()); | ||
90 | return result; | ||
91 | } | ||
92 | |||
93 | using ::android::hardware::keymaster::V4_0::HardwareAuthToken; | ||
94 | using ::android::hardware::keymaster::V4_0::HardwareAuthenticatorType; | ||
95 | |||
96 | template <typename T> | ||
97 | auto toBytes(const T& v) -> const uint8_t (&)[sizeof(T)] { | ||
98 | return *reinterpret_cast<const uint8_t(*)[sizeof(T)]>(&v); | ||
99 | } | ||
100 | |||
101 | HardwareAuthToken makeTestToken(const TestModeCommands command, uint64_t timestamp = 0) { | ||
102 | HardwareAuthToken auth_token; | ||
103 | auth_token.challenge = static_cast<uint64_t>(command); | ||
104 | auth_token.userId = 0; | ||
105 | auth_token.authenticatorId = 0; | ||
106 | auth_token.authenticatorType = HardwareAuthenticatorType::NONE; | ||
107 | auth_token.timestamp = timestamp; | ||
108 | |||
109 | // Canonical form of auth-token v0 | ||
110 | // version (1 byte) | ||
111 | // challenge (8 bytes) | ||
112 | // user_id (8 bytes) | ||
113 | // authenticator_id (8 bytes) | ||
114 | // authenticator_type (4 bytes) | ||
115 | // timestamp (8 bytes) | ||
116 | // total 37 bytes | ||
117 | auth_token.mac = testHMAC("\0", | ||
118 | toBytes(auth_token.challenge), // | ||
119 | toBytes(auth_token.userId), // | ||
120 | toBytes(auth_token.authenticatorId), // | ||
121 | toBytes(support::hton(auth_token.authenticatorType)), // | ||
122 | toBytes(support::hton(auth_token.timestamp))); // | ||
123 | |||
124 | return auth_token; | ||
125 | } | ||
126 | |||
127 | #define DEBUG_CONFRIMATIONUI_UTILS_TEST | ||
128 | |||
129 | #ifdef DEBUG_CONFRIMATIONUI_UTILS_TEST | ||
130 | std::ostream& hexdump(std::ostream& out, const uint8_t* data, size_t size) { | ||
131 | for (size_t i = 0; i < size; ++i) { | ||
132 | uint8_t byte = data[i]; | ||
133 | out << std::hex << std::setw(2) << std::setfill('0') << (unsigned)byte; | ||
134 | switch (i & 0xf) { | ||
135 | case 0xf: | ||
136 | out << "\n"; | ||
137 | break; | ||
138 | case 7: | ||
139 | out << " "; | ||
140 | break; | ||
141 | default: | ||
142 | out << " "; | ||
143 | break; | ||
144 | } | ||
145 | } | ||
146 | return out; | ||
147 | } | ||
148 | #endif | ||
149 | |||
150 | constexpr char hex_value[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // | ||
151 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // | ||
152 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // | ||
153 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // '0'..'9' | ||
154 | 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'A'..'F' | ||
155 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // | ||
156 | 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'a'..'f' | ||
157 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // | ||
158 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // | ||
159 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // | ||
160 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // | ||
161 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // | ||
162 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // | ||
163 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // | ||
164 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // | ||
165 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
166 | |||
167 | std::string hex2str(std::string a) { | ||
168 | std::string b; | ||
169 | size_t num = a.size() / 2; | ||
170 | b.resize(num); | ||
171 | for (size_t i = 0; i < num; i++) { | ||
172 | b[i] = (hex_value[a[i * 2] & 0xFF] << 4) + (hex_value[a[i * 2 + 1] & 0xFF]); | ||
173 | } | ||
174 | return b; | ||
175 | } | ||
176 | |||
177 | } // namespace | ||
178 | |||
179 | class ConfirmationArgs { | ||
180 | public: | ||
181 | ResponseCode error_; | ||
182 | hidl_vec<uint8_t> formattedMessage_; | ||
183 | hidl_vec<uint8_t> confirmationToken_; | ||
184 | bool verifyConfirmationToken() { | ||
185 | static constexpr char confirmationPrefix[] = "confirmation token"; | ||
186 | EXPECT_EQ(32U, confirmationToken_.size()); | ||
187 | return 32U == confirmationToken_.size() && | ||
188 | !memcmp(confirmationToken_.data(), | ||
189 | testHMAC(confirmationPrefix, formattedMessage_).data(), 32); | ||
190 | } | ||
191 | }; | ||
192 | |||
193 | class ConfirmationTestCallback : public ::testing::VtsHalHidlTargetCallbackBase<ConfirmationArgs>, | ||
194 | public IConfirmationResultCallback { | ||
195 | public: | ||
196 | Return<void> result(ResponseCode error, const hidl_vec<uint8_t>& formattedMessage, | ||
197 | const hidl_vec<uint8_t>& confirmationToken) override { | ||
198 | ConfirmationArgs args; | ||
199 | args.error_ = error; | ||
200 | args.formattedMessage_ = formattedMessage; | ||
201 | args.confirmationToken_ = confirmationToken; | ||
202 | NotifyFromCallback(args); | ||
203 | return Void(); | ||
204 | } | ||
205 | }; | ||
206 | |||
207 | class ConfirmationUIHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { | ||
208 | public: | ||
209 | // get the test environment singleton | ||
210 | static ConfirmationUIHidlEnvironment* Instance() { | ||
211 | static ConfirmationUIHidlEnvironment* instance = new ConfirmationUIHidlEnvironment; | ||
212 | return instance; | ||
213 | } | ||
214 | |||
215 | void registerTestServices() override { registerTestService<IConfirmationUI>(); } | ||
216 | |||
217 | private: | ||
218 | ConfirmationUIHidlEnvironment(){}; | ||
219 | |||
220 | GTEST_DISALLOW_COPY_AND_ASSIGN_(ConfirmationUIHidlEnvironment); | ||
221 | }; | ||
222 | |||
223 | class ConfirmationUIHidlTest : public ::testing::VtsHalHidlTargetTestBase { | ||
224 | public: | ||
225 | void TearDown() override { confirmator().abort(); } | ||
226 | |||
227 | static void SetUpTestCase() { | ||
228 | string service_name = | ||
229 | ConfirmationUIHidlEnvironment::Instance()->getServiceName<IConfirmationUI>(); | ||
230 | confirmator_ = IConfirmationUI::getService(service_name); | ||
231 | ASSERT_NE(nullptr, confirmator_.get()); | ||
232 | } | ||
233 | |||
234 | static void TearDownTestCase() { confirmator_.clear(); } | ||
235 | |||
236 | static IConfirmationUI& confirmator() { return *confirmator_; } | ||
237 | |||
238 | private: | ||
239 | static sp<IConfirmationUI> confirmator_; | ||
240 | }; | ||
241 | |||
242 | sp<IConfirmationUI> ConfirmationUIHidlTest::confirmator_; | ||
243 | |||
244 | #define ASSERT_HAL_CALL(expected, call) \ | ||
245 | { \ | ||
246 | auto result = call; \ | ||
247 | ASSERT_TRUE(result.isOk()); \ | ||
248 | ASSERT_EQ(expected, static_cast<decltype(expected)>(result)); \ | ||
249 | } | ||
250 | |||
251 | struct CnCborDeleter { | ||
252 | void operator()(cn_cbor* ptr) { cn_cbor_free(ptr); } | ||
253 | }; | ||
254 | |||
255 | typedef std::unique_ptr<cn_cbor, CnCborDeleter> CnCborPtr; | ||
256 | |||
257 | // Simulates the User taping Ok | ||
258 | TEST_F(ConfirmationUIHidlTest, UserOkTest) { | ||
259 | static constexpr char test_prompt[] = "Me first, gimme gimme!"; | ||
260 | static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3}; | ||
261 | sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback; | ||
262 | hidl_string prompt_text(test_prompt); | ||
263 | hidl_vec<uint8_t> extra(test_extra, test_extra + 3); | ||
264 | ASSERT_HAL_CALL(ResponseCode::OK, | ||
265 | confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {})); | ||
266 | |||
267 | ASSERT_HAL_CALL(ResponseCode::OK, confirmator().deliverSecureInputEvent( | ||
268 | makeTestToken(TestModeCommands::OK_EVENT))); | ||
269 | |||
270 | auto result = conf_cb->WaitForCallback(); | ||
271 | ASSERT_EQ(ResponseCode::OK, result.args->error_); | ||
272 | |||
273 | ASSERT_TRUE(result.args->verifyConfirmationToken()); | ||
274 | |||
275 | cn_cbor_errback cn_cbor_error; | ||
276 | auto parsed_message = | ||
277 | CnCborPtr(cn_cbor_decode(result.args->formattedMessage_.data(), | ||
278 | result.args->formattedMessage_.size(), &cn_cbor_error)); | ||
279 | // is parsable CBOR | ||
280 | ASSERT_TRUE(parsed_message.get()); | ||
281 | // is a map | ||
282 | ASSERT_EQ(CN_CBOR_MAP, parsed_message->type); | ||
283 | |||
284 | // the message must have exactly 2 key value pairs. | ||
285 | // cn_cbor holds 2*<no_of_pairs> in the length field | ||
286 | ASSERT_EQ(4, parsed_message->length); | ||
287 | // map has key "prompt" | ||
288 | auto prompt = cn_cbor_mapget_string(parsed_message.get(), "prompt"); | ||
289 | ASSERT_TRUE(prompt); | ||
290 | ASSERT_EQ(CN_CBOR_TEXT, prompt->type); | ||
291 | ASSERT_EQ(22, prompt->length); | ||
292 | ASSERT_EQ(0, memcmp(test_prompt, prompt->v.str, 22)); | ||
293 | // map has key "extra" | ||
294 | auto extra_out = cn_cbor_mapget_string(parsed_message.get(), "extra"); | ||
295 | ASSERT_TRUE(extra_out); | ||
296 | ASSERT_EQ(CN_CBOR_BYTES, extra_out->type); | ||
297 | ASSERT_EQ(3, extra_out->length); | ||
298 | ASSERT_EQ(0, memcmp(test_extra, extra_out->v.bytes, 3)); | ||
299 | } | ||
300 | |||
301 | // Initiates a confirmation prompt with a message that is too long | ||
302 | TEST_F(ConfirmationUIHidlTest, MessageTooLongTest) { | ||
303 | static constexpr uint8_t test_extra[static_cast<uint32_t>(MessageSize::MAX)] = {}; | ||
304 | static constexpr char test_prompt[] = "D\'oh!"; | ||
305 | sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback; | ||
306 | hidl_string prompt_text(test_prompt); | ||
307 | hidl_vec<uint8_t> extra(test_extra, test_extra + sizeof(test_extra)); | ||
308 | ASSERT_HAL_CALL(ResponseCode::UIErrorMessageTooLong, | ||
309 | confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {})); | ||
310 | } | ||
311 | |||
312 | // If the message gets very long some HAL implementations might fail even before the message | ||
313 | // reaches the trusted app implementation. But the HAL must still diagnose the correct error. | ||
314 | TEST_F(ConfirmationUIHidlTest, MessageWayTooLongTest) { | ||
315 | static constexpr uint8_t test_extra[static_cast<uint32_t>(MessageSize::MAX) * 10] = {}; | ||
316 | static constexpr char test_prompt[] = "D\'oh!"; | ||
317 | sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback; | ||
318 | hidl_string prompt_text(test_prompt); | ||
319 | hidl_vec<uint8_t> extra(test_extra, test_extra + sizeof(test_extra)); | ||
320 | ASSERT_HAL_CALL(ResponseCode::UIErrorMessageTooLong, | ||
321 | confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {})); | ||
322 | } | ||
323 | |||
324 | // Simulates the User tapping the Cancel | ||
325 | TEST_F(ConfirmationUIHidlTest, UserCancelTest) { | ||
326 | static constexpr char test_prompt[] = "Me first, gimme gimme!"; | ||
327 | static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3}; | ||
328 | sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback; | ||
329 | hidl_string prompt_text(test_prompt); | ||
330 | hidl_vec<uint8_t> extra(test_extra, test_extra + 3); | ||
331 | ASSERT_HAL_CALL(ResponseCode::OK, | ||
332 | confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {})); | ||
333 | |||
334 | ASSERT_HAL_CALL(ResponseCode::OK, confirmator().deliverSecureInputEvent( | ||
335 | makeTestToken(TestModeCommands::CANCEL_EVENT))); | ||
336 | |||
337 | auto result = conf_cb->WaitForCallback(); | ||
338 | ASSERT_EQ(ResponseCode::Canceled, result.args->error_); | ||
339 | |||
340 | ASSERT_EQ(0U, result.args->confirmationToken_.size()); | ||
341 | ASSERT_EQ(0U, result.args->formattedMessage_.size()); | ||
342 | } | ||
343 | |||
344 | // Simulates the framework candelling an ongoing prompt | ||
345 | TEST_F(ConfirmationUIHidlTest, AbortTest) { | ||
346 | static constexpr char test_prompt[] = "Me first, gimme gimme!"; | ||
347 | static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3}; | ||
348 | sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback; | ||
349 | hidl_string prompt_text(test_prompt); | ||
350 | hidl_vec<uint8_t> extra(test_extra, test_extra + 3); | ||
351 | ASSERT_HAL_CALL(ResponseCode::OK, | ||
352 | confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {})); | ||
353 | |||
354 | confirmator().abort(); | ||
355 | |||
356 | auto result = conf_cb->WaitForCallback(); | ||
357 | ASSERT_EQ(ResponseCode::Aborted, result.args->error_); | ||
358 | ASSERT_EQ(0U, result.args->confirmationToken_.size()); | ||
359 | ASSERT_EQ(0U, result.args->formattedMessage_.size()); | ||
360 | } | ||
361 | |||
362 | // Passing malformed UTF-8 to the confirmation UI | ||
363 | // This test passes a string that ends in the middle of a multibyte character | ||
364 | TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test1) { | ||
365 | static constexpr char test_prompt[] = {char(0xc0), 0}; | ||
366 | static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3}; | ||
367 | sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback; | ||
368 | hidl_string prompt_text(test_prompt); | ||
369 | hidl_vec<uint8_t> extra(test_extra, test_extra + 3); | ||
370 | ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding, | ||
371 | confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {})); | ||
372 | } | ||
373 | |||
374 | // Passing malformed UTF-8 to the confirmation UI | ||
375 | // This test passes a string with a 5-byte character. | ||
376 | TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test2) { | ||
377 | static constexpr char test_prompt[] = {char(0xf8), char(0x82), char(0x82), | ||
378 | char(0x82), char(0x82), 0}; | ||
379 | static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3}; | ||
380 | sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback; | ||
381 | hidl_string prompt_text(test_prompt); | ||
382 | hidl_vec<uint8_t> extra(test_extra, test_extra + 3); | ||
383 | ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding, | ||
384 | confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {})); | ||
385 | } | ||
386 | |||
387 | // Passing malformed UTF-8 to the confirmation UI | ||
388 | // This test passes a string with a 2-byte character followed by a stray non UTF-8 character. | ||
389 | TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test3) { | ||
390 | static constexpr char test_prompt[] = {char(0xc0), char(0x82), char(0x83), 0}; | ||
391 | static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3}; | ||
392 | sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback; | ||
393 | hidl_string prompt_text(test_prompt); | ||
394 | hidl_vec<uint8_t> extra(test_extra, test_extra + 3); | ||
395 | ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding, | ||
396 | confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {})); | ||
397 | } | ||
398 | |||
399 | // Test the implementation of HMAC SHA 256 against a golden blob. | ||
400 | TEST(ConfirmationUITestSelfTest, HMAC256SelfTest) { | ||
401 | const char key_str[32] = "keykeykeykeykeykeykeykeykeykeyk"; | ||
402 | const uint8_t(&key)[32] = *reinterpret_cast<const uint8_t(*)[32]>(key_str); | ||
403 | auto expected = hex2str("2377fbcaa7fb3f6c20cfa1d9ebc60e9922cf58c909e25e300f3cb57f7805c886"); | ||
404 | auto result = HMacer::hmac256(key, "value1", "value2", "value3"); | ||
405 | |||
406 | #ifdef DEBUG_CONFRIMATIONUI_UTILS_TEST | ||
407 | hexdump(std::cout, reinterpret_cast<const uint8_t*>(expected.data()), 32) << std::endl; | ||
408 | hexdump(std::cout, result.value().data(), 32) << std::endl; | ||
409 | #endif | ||
410 | |||
411 | support::ByteBufferProxy expected_bytes(expected); | ||
412 | ASSERT_TRUE(result.isOk()); | ||
413 | ASSERT_EQ(expected, result.value()); | ||
414 | } | ||
415 | |||
416 | } // namespace test | ||
417 | } // namespace V1_0 | ||
418 | } // namespace confirmationui | ||
419 | } // namespace hardware | ||
420 | } // namespace android | ||
421 | |||
422 | int main(int argc, char** argv) { | ||
423 | ::testing::InitGoogleTest(&argc, argv); | ||
424 | std::vector<std::string> positional_args; | ||
425 | int status = RUN_ALL_TESTS(); | ||
426 | ALOGI("Test result = %d", status); | ||
427 | return status; | ||
428 | } | ||
diff --git a/gnss/1.1/Android.bp b/gnss/1.1/Android.bp index 417b4f5b..4ae4439a 100644 --- a/gnss/1.1/Android.bp +++ b/gnss/1.1/Android.bp | |||
@@ -11,6 +11,7 @@ hidl_interface { | |||
11 | "IGnssCallback.hal", | 11 | "IGnssCallback.hal", |
12 | "IGnssConfiguration.hal", | 12 | "IGnssConfiguration.hal", |
13 | "IGnssMeasurement.hal", | 13 | "IGnssMeasurement.hal", |
14 | "IGnssMeasurementCallback.hal", | ||
14 | ], | 15 | ], |
15 | interfaces: [ | 16 | interfaces: [ |
16 | "android.hardware.gnss@1.0", | 17 | "android.hardware.gnss@1.0", |
diff --git a/gnss/1.1/IGnssMeasurement.hal b/gnss/1.1/IGnssMeasurement.hal index 75df5a8a..cd83ae35 100644 --- a/gnss/1.1/IGnssMeasurement.hal +++ b/gnss/1.1/IGnssMeasurement.hal | |||
@@ -17,7 +17,7 @@ | |||
17 | package android.hardware.gnss@1.1; | 17 | package android.hardware.gnss@1.1; |
18 | 18 | ||
19 | import @1.0::IGnssMeasurement; | 19 | import @1.0::IGnssMeasurement; |
20 | import @1.0::IGnssMeasurementCallback; | 20 | import IGnssMeasurementCallback; |
21 | 21 | ||
22 | /** | 22 | /** |
23 | * Extended interface for GNSS Measurements support. | 23 | * Extended interface for GNSS Measurements support. |
diff --git a/gnss/1.1/IGnssMeasurementCallback.hal b/gnss/1.1/IGnssMeasurementCallback.hal new file mode 100644 index 00000000..5a60a56b --- /dev/null +++ b/gnss/1.1/IGnssMeasurementCallback.hal | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | package android.hardware.gnss@1.1; | ||
18 | |||
19 | import @1.0::IGnssMeasurementCallback; | ||
20 | |||
21 | /** The callback interface to report measurements from the HAL. */ | ||
22 | interface IGnssMeasurementCallback extends @1.0::IGnssMeasurementCallback { | ||
23 | /** | ||
24 | * Flags indicating the Accumulated Delta Range's states. | ||
25 | */ | ||
26 | enum GnssAccumulatedDeltaRangeState | ||
27 | : @1.0::IGnssMeasurementCallback.GnssAccumulatedDeltaRangeState { | ||
28 | ADR_STATE_HALF_CYCLE_RESOLVED = 1 << 3, // Carrier-phase half-cycle ambiguity resolved | ||
29 | }; | ||
30 | |||
31 | /** | ||
32 | * Extends a GNSS Measurement, adding the new enum. | ||
33 | */ | ||
34 | struct GnssMeasurement { | ||
35 | /** | ||
36 | * GNSS measurement information for a single satellite and frequency, as in the 1.0 | ||
37 | * version of the HAL. | ||
38 | * | ||
39 | * In this version of the HAL, these fields of the | ||
40 | * @1.0::IGnssMeasurementCallback.GnssMeasurement v1_0 struct are deprecated, and | ||
41 | * are no longer used by the framework: | ||
42 | * carrierCycles | ||
43 | * carrierPhase | ||
44 | * carrierPhaseUncertainty | ||
45 | * | ||
46 | * Similar information about carrier phase signal tracking is still reported in these | ||
47 | * fields of @1.0::IGnssMeasurementCallback.GnssMeasurement v1_0: | ||
48 | * accumulatedDeltaRangeM | ||
49 | * accumulatedDeltaRangeUncertaintyM | ||
50 | */ | ||
51 | @1.0::IGnssMeasurementCallback.GnssMeasurement v1_0; | ||
52 | |||
53 | /** | ||
54 | * Provides the state of Accumulated Delta Range values, including additional information | ||
55 | * beyond version 1.0 of the HAL. See GnssAccumulatedDeltaRangeState. | ||
56 | * | ||
57 | * In this (1.1) version of the HAL, this value is used by the framework, not the | ||
58 | * value provided by v1_0.accumulatedDeltaRangeState. | ||
59 | */ | ||
60 | bitfield<GnssAccumulatedDeltaRangeState> accumulatedDeltaRangeState; | ||
61 | }; | ||
62 | |||
63 | /** | ||
64 | * Complete set of GNSS Measurement data, same as 1.0 with additional enum in measurements. | ||
65 | */ | ||
66 | struct GnssData { | ||
67 | /** The full set of satellite measurement observations. */ | ||
68 | vec<GnssMeasurement> measurements; | ||
69 | |||
70 | /** The GNSS clock time reading. */ | ||
71 | GnssClock clock; | ||
72 | }; | ||
73 | |||
74 | /** | ||
75 | * Callback for the hal to pass a GnssData structure back to the client. | ||
76 | * | ||
77 | * @param data Contains a reading of GNSS measurements. | ||
78 | */ | ||
79 | gnssMeasurementCb(GnssData data); | ||
80 | }; | ||
diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp index 264a11db..a0a1c736 100644 --- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp +++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp | |||
@@ -396,6 +396,10 @@ TEST_F(GnssHalTest, InjectBestLocation) { | |||
396 | 396 | ||
397 | ASSERT_TRUE(result.isOk()); | 397 | ASSERT_TRUE(result.isOk()); |
398 | EXPECT_TRUE(result); | 398 | EXPECT_TRUE(result); |
399 | |||
400 | auto resultVoid = gnss_hal_->deleteAidingData(IGnss::GnssAidingData::DELETE_ALL); | ||
401 | |||
402 | ASSERT_TRUE(resultVoid.isOk()); | ||
399 | } | 403 | } |
400 | 404 | ||
401 | /* | 405 | /* |
diff --git a/graphics/composer/2.1/default/Android.bp b/graphics/composer/2.1/default/Android.bp index b46a1deb..2de1e3ca 100644 --- a/graphics/composer/2.1/default/Android.bp +++ b/graphics/composer/2.1/default/Android.bp | |||
@@ -1,34 +1,12 @@ | |||
1 | cc_library_static { | ||
2 | name: "libhwcomposer-client", | ||
3 | vendor_available: true, | ||
4 | defaults: ["hidl_defaults"], | ||
5 | export_include_dirs: ["."], | ||
6 | srcs: ["ComposerClient.cpp"], | ||
7 | shared_libs: [ | ||
8 | "android.hardware.graphics.composer@2.1", | ||
9 | "android.hardware.graphics.mapper@2.0", | ||
10 | "libbase", | ||
11 | "libcutils", | ||
12 | "libfmq", | ||
13 | "libhardware", | ||
14 | "libhidlbase", | ||
15 | "libhidltransport", | ||
16 | "liblog", | ||
17 | "libsync", | ||
18 | "libutils", | ||
19 | ], | ||
20 | header_libs: [ | ||
21 | "android.hardware.graphics.composer@2.1-command-buffer", | ||
22 | ], | ||
23 | } | ||
24 | |||
25 | cc_library_shared { | 1 | cc_library_shared { |
26 | name: "android.hardware.graphics.composer@2.1-impl", | 2 | name: "android.hardware.graphics.composer@2.1-impl", |
27 | defaults: ["hidl_defaults"], | 3 | defaults: ["hidl_defaults"], |
28 | proprietary: true, | 4 | vendor: true, |
29 | relative_install_path: "hw", | 5 | relative_install_path: "hw", |
30 | srcs: ["Hwc.cpp"], | 6 | srcs: ["passthrough.cpp"], |
31 | static_libs: ["libhwcomposer-client"], | 7 | header_libs: [ |
8 | "android.hardware.graphics.composer@2.1-passthrough", | ||
9 | ], | ||
32 | shared_libs: [ | 10 | shared_libs: [ |
33 | "android.hardware.graphics.composer@2.1", | 11 | "android.hardware.graphics.composer@2.1", |
34 | "android.hardware.graphics.mapper@2.0", | 12 | "android.hardware.graphics.mapper@2.0", |
@@ -44,26 +22,21 @@ cc_library_shared { | |||
44 | "libhwc2on1adapter", | 22 | "libhwc2on1adapter", |
45 | "libhwc2onfbadapter", | 23 | "libhwc2onfbadapter", |
46 | ], | 24 | ], |
47 | header_libs: [ | 25 | cflags: [ |
48 | "android.hardware.graphics.composer@2.1-command-buffer", | 26 | "-DLOG_TAG=\"ComposerHal\"" |
49 | ], | 27 | ], |
50 | } | 28 | } |
51 | 29 | ||
52 | cc_binary { | 30 | cc_binary { |
53 | name: "android.hardware.graphics.composer@2.1-service", | 31 | name: "android.hardware.graphics.composer@2.1-service", |
54 | defaults: ["hidl_defaults"], | 32 | defaults: ["hidl_defaults"], |
55 | proprietary: true, | 33 | vendor: true, |
56 | relative_install_path: "hw", | 34 | relative_install_path: "hw", |
57 | srcs: ["service.cpp"], | 35 | srcs: ["service.cpp"], |
58 | init_rc: ["android.hardware.graphics.composer@2.1-service.rc"], | 36 | init_rc: ["android.hardware.graphics.composer@2.1-service.rc"], |
59 | static_libs: ["libhwcomposer-client"], | ||
60 | shared_libs: [ | 37 | shared_libs: [ |
61 | "android.hardware.graphics.composer@2.1", | 38 | "android.hardware.graphics.composer@2.1", |
62 | "libbase", | ||
63 | "libbinder", | 39 | "libbinder", |
64 | "libcutils", | ||
65 | "libfmq", | ||
66 | "libhardware", | ||
67 | "libhidlbase", | 40 | "libhidlbase", |
68 | "libhidltransport", | 41 | "libhidltransport", |
69 | "liblog", | 42 | "liblog", |
diff --git a/graphics/composer/2.1/default/ComposerBase.h b/graphics/composer/2.1/default/ComposerBase.h deleted file mode 100644 index e1c9d333..00000000 --- a/graphics/composer/2.1/default/ComposerBase.h +++ /dev/null | |||
@@ -1,132 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2017 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_BASE_H | ||
18 | #define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_BASE_H | ||
19 | |||
20 | #include <android/hardware/graphics/composer/2.1/IComposer.h> | ||
21 | #include <hardware/hwcomposer2.h> | ||
22 | |||
23 | namespace android { | ||
24 | namespace hardware { | ||
25 | namespace graphics { | ||
26 | namespace composer { | ||
27 | namespace V2_1 { | ||
28 | namespace implementation { | ||
29 | |||
30 | using android::hardware::graphics::common::V1_0::PixelFormat; | ||
31 | using android::hardware::graphics::common::V1_0::Transform; | ||
32 | using android::hardware::graphics::common::V1_0::Dataspace; | ||
33 | using android::hardware::graphics::common::V1_0::ColorMode; | ||
34 | using android::hardware::graphics::common::V1_0::ColorTransform; | ||
35 | using android::hardware::graphics::common::V1_0::Hdr; | ||
36 | |||
37 | class ComposerBase { | ||
38 | public: | ||
39 | virtual ~ComposerBase() {}; | ||
40 | |||
41 | virtual bool hasCapability(hwc2_capability_t capability) = 0; | ||
42 | |||
43 | virtual void removeClient() = 0; | ||
44 | virtual void enableCallback(bool enable) = 0; | ||
45 | virtual uint32_t getMaxVirtualDisplayCount() = 0; | ||
46 | virtual Error createVirtualDisplay(uint32_t width, uint32_t height, | ||
47 | PixelFormat* format, Display* outDisplay) = 0; | ||
48 | virtual Error destroyVirtualDisplay(Display display) = 0; | ||
49 | virtual Error createLayer(Display display, Layer* outLayer) = 0; | ||
50 | virtual Error destroyLayer(Display display, Layer layer) = 0; | ||
51 | |||
52 | virtual Error getActiveConfig(Display display, Config* outConfig) = 0; | ||
53 | virtual Error getClientTargetSupport(Display display, | ||
54 | uint32_t width, uint32_t height, | ||
55 | PixelFormat format, Dataspace dataspace) = 0; | ||
56 | virtual Error getColorModes(Display display, | ||
57 | hidl_vec<ColorMode>* outModes) = 0; | ||
58 | virtual Error getDisplayAttribute(Display display, Config config, | ||
59 | IComposerClient::Attribute attribute, int32_t* outValue) = 0; | ||
60 | virtual Error getDisplayConfigs(Display display, | ||
61 | hidl_vec<Config>* outConfigs) = 0; | ||
62 | virtual Error getDisplayName(Display display, hidl_string* outName) = 0; | ||
63 | virtual Error getDisplayType(Display display, | ||
64 | IComposerClient::DisplayType* outType) = 0; | ||
65 | virtual Error getDozeSupport(Display display, bool* outSupport) = 0; | ||
66 | virtual Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes, | ||
67 | float* outMaxLuminance, float* outMaxAverageLuminance, | ||
68 | float* outMinLuminance) = 0; | ||
69 | |||
70 | virtual Error setActiveConfig(Display display, Config config) = 0; | ||
71 | virtual Error setColorMode(Display display, ColorMode mode) = 0; | ||
72 | virtual Error setPowerMode(Display display, | ||
73 | IComposerClient::PowerMode mode) = 0; | ||
74 | virtual Error setVsyncEnabled(Display display, | ||
75 | IComposerClient::Vsync enabled) = 0; | ||
76 | |||
77 | virtual Error setColorTransform(Display display, const float* matrix, | ||
78 | int32_t hint) = 0; | ||
79 | virtual Error setClientTarget(Display display, buffer_handle_t target, | ||
80 | int32_t acquireFence, int32_t dataspace, | ||
81 | const std::vector<hwc_rect_t>& damage) = 0; | ||
82 | virtual Error setOutputBuffer(Display display, buffer_handle_t buffer, | ||
83 | int32_t releaseFence) = 0; | ||
84 | virtual Error validateDisplay(Display display, | ||
85 | std::vector<Layer>* outChangedLayers, | ||
86 | std::vector<IComposerClient::Composition>* outCompositionTypes, | ||
87 | uint32_t* outDisplayRequestMask, | ||
88 | std::vector<Layer>* outRequestedLayers, | ||
89 | std::vector<uint32_t>* outRequestMasks) = 0; | ||
90 | virtual Error acceptDisplayChanges(Display display) = 0; | ||
91 | virtual Error presentDisplay(Display display, int32_t* outPresentFence, | ||
92 | std::vector<Layer>* outLayers, | ||
93 | std::vector<int32_t>* outReleaseFences) = 0; | ||
94 | |||
95 | virtual Error setLayerCursorPosition(Display display, Layer layer, | ||
96 | int32_t x, int32_t y) = 0; | ||
97 | virtual Error setLayerBuffer(Display display, Layer layer, | ||
98 | buffer_handle_t buffer, int32_t acquireFence) = 0; | ||
99 | virtual Error setLayerSurfaceDamage(Display display, Layer layer, | ||
100 | const std::vector<hwc_rect_t>& damage) = 0; | ||
101 | virtual Error setLayerBlendMode(Display display, Layer layer, | ||
102 | int32_t mode) = 0; | ||
103 | virtual Error setLayerColor(Display display, Layer layer, | ||
104 | IComposerClient::Color color) = 0; | ||
105 | virtual Error setLayerCompositionType(Display display, Layer layer, | ||
106 | int32_t type) = 0; | ||
107 | virtual Error setLayerDataspace(Display display, Layer layer, | ||
108 | int32_t dataspace) = 0; | ||
109 | virtual Error setLayerDisplayFrame(Display display, Layer layer, | ||
110 | const hwc_rect_t& frame) = 0; | ||
111 | virtual Error setLayerPlaneAlpha(Display display, Layer layer, | ||
112 | float alpha) = 0; | ||
113 | virtual Error setLayerSidebandStream(Display display, Layer layer, | ||
114 | buffer_handle_t stream) = 0; | ||
115 | virtual Error setLayerSourceCrop(Display display, Layer layer, | ||
116 | const hwc_frect_t& crop) = 0; | ||
117 | virtual Error setLayerTransform(Display display, Layer layer, | ||
118 | int32_t transform) = 0; | ||
119 | virtual Error setLayerVisibleRegion(Display display, Layer layer, | ||
120 | const std::vector<hwc_rect_t>& visible) = 0; | ||
121 | virtual Error setLayerZOrder(Display display, Layer layer, | ||
122 | uint32_t z) = 0; | ||
123 | }; | ||
124 | |||
125 | } // namespace implementation | ||
126 | } // namespace V2_1 | ||
127 | } // namespace composer | ||
128 | } // namespace graphics | ||
129 | } // namespace hardware | ||
130 | } // namespace android | ||
131 | |||
132 | #endif // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_BASE_H | ||
diff --git a/graphics/composer/2.1/default/ComposerClient.cpp b/graphics/composer/2.1/default/ComposerClient.cpp deleted file mode 100644 index 0fcb9de8..00000000 --- a/graphics/composer/2.1/default/ComposerClient.cpp +++ /dev/null | |||
@@ -1,1205 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #define LOG_TAG "HwcPassthrough" | ||
18 | |||
19 | #include <android/hardware/graphics/mapper/2.0/IMapper.h> | ||
20 | #include <log/log.h> | ||
21 | |||
22 | #include "ComposerBase.h" | ||
23 | #include "ComposerClient.h" | ||
24 | |||
25 | namespace android { | ||
26 | namespace hardware { | ||
27 | namespace graphics { | ||
28 | namespace composer { | ||
29 | namespace V2_1 { | ||
30 | namespace implementation { | ||
31 | |||
32 | namespace { | ||
33 | |||
34 | using MapperError = android::hardware::graphics::mapper::V2_0::Error; | ||
35 | using android::hardware::graphics::mapper::V2_0::IMapper; | ||
36 | |||
37 | class HandleImporter { | ||
38 | public: | ||
39 | bool initialize() | ||
40 | { | ||
41 | // allow only one client | ||
42 | if (mInitialized) { | ||
43 | return false; | ||
44 | } | ||
45 | |||
46 | mMapper = IMapper::getService(); | ||
47 | |||
48 | mInitialized = true; | ||
49 | return true; | ||
50 | } | ||
51 | |||
52 | void cleanup() | ||
53 | { | ||
54 | mMapper.clear(); | ||
55 | mInitialized = false; | ||
56 | } | ||
57 | |||
58 | // In IComposer, any buffer_handle_t is owned by the caller and we need to | ||
59 | // make a clone for hwcomposer2. We also need to translate empty handle | ||
60 | // to nullptr. This function does that, in-place. | ||
61 | bool importBuffer(buffer_handle_t& handle) | ||
62 | { | ||
63 | if (!handle) { | ||
64 | return true; | ||
65 | } | ||
66 | |||
67 | if (!handle->numFds && !handle->numInts) { | ||
68 | handle = nullptr; | ||
69 | return true; | ||
70 | } | ||
71 | |||
72 | MapperError error; | ||
73 | buffer_handle_t importedHandle; | ||
74 | mMapper->importBuffer( | ||
75 | hidl_handle(handle), | ||
76 | [&](const auto& tmpError, const auto& tmpBufferHandle) { | ||
77 | error = tmpError; | ||
78 | importedHandle = static_cast<buffer_handle_t>(tmpBufferHandle); | ||
79 | }); | ||
80 | if (error != MapperError::NONE) { | ||
81 | return false; | ||
82 | } | ||
83 | |||
84 | handle = importedHandle; | ||
85 | |||
86 | return true; | ||
87 | } | ||
88 | |||
89 | void freeBuffer(buffer_handle_t handle) | ||
90 | { | ||
91 | if (!handle) { | ||
92 | return; | ||
93 | } | ||
94 | |||
95 | mMapper->freeBuffer(const_cast<native_handle_t*>(handle)); | ||
96 | } | ||
97 | |||
98 | private: | ||
99 | bool mInitialized = false; | ||
100 | sp<IMapper> mMapper; | ||
101 | }; | ||
102 | |||
103 | HandleImporter sHandleImporter; | ||
104 | |||
105 | } // anonymous namespace | ||
106 | |||
107 | BufferCacheEntry::BufferCacheEntry() | ||
108 | : mHandle(nullptr) | ||
109 | { | ||
110 | } | ||
111 | |||
112 | BufferCacheEntry::BufferCacheEntry(BufferCacheEntry&& other) | ||
113 | { | ||
114 | mHandle = other.mHandle; | ||
115 | other.mHandle = nullptr; | ||
116 | } | ||
117 | |||
118 | BufferCacheEntry& BufferCacheEntry::operator=(buffer_handle_t handle) | ||
119 | { | ||
120 | clear(); | ||
121 | mHandle = handle; | ||
122 | return *this; | ||
123 | } | ||
124 | |||
125 | BufferCacheEntry::~BufferCacheEntry() | ||
126 | { | ||
127 | clear(); | ||
128 | } | ||
129 | |||
130 | void BufferCacheEntry::clear() | ||
131 | { | ||
132 | if (mHandle) { | ||
133 | sHandleImporter.freeBuffer(mHandle); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | ComposerClient::ComposerClient(ComposerBase& hal) | ||
138 | : mHal(hal), mWriter(kWriterInitialSize) | ||
139 | { | ||
140 | } | ||
141 | |||
142 | ComposerClient::~ComposerClient() | ||
143 | { | ||
144 | // We want to call hwc2_close here (and move hwc2_open to the | ||
145 | // constructor), with the assumption that hwc2_close would | ||
146 | // | ||
147 | // - clean up all resources owned by the client | ||
148 | // - make sure all displays are blank (since there is no layer) | ||
149 | // | ||
150 | // But since SF used to crash at this point, different hwcomposer2 | ||
151 | // implementations behave differently on hwc2_close. Our only portable | ||
152 | // choice really is to abort(). But that is not an option anymore | ||
153 | // because we might also have VTS or VR as clients that can come and go. | ||
154 | // | ||
155 | // Below we manually clean all resources (layers and virtual | ||
156 | // displays), and perform a presentDisplay afterwards. | ||
157 | ALOGW("destroying composer client"); | ||
158 | |||
159 | mHal.enableCallback(false); | ||
160 | |||
161 | // no need to grab the mutex as any in-flight hwbinder call would have | ||
162 | // kept the client alive | ||
163 | for (const auto& dpy : mDisplayData) { | ||
164 | ALOGW("destroying client resources for display %" PRIu64, dpy.first); | ||
165 | |||
166 | for (const auto& ly : dpy.second.Layers) { | ||
167 | mHal.destroyLayer(dpy.first, ly.first); | ||
168 | } | ||
169 | |||
170 | if (dpy.second.IsVirtual) { | ||
171 | mHal.destroyVirtualDisplay(dpy.first); | ||
172 | } else { | ||
173 | ALOGW("performing a final presentDisplay"); | ||
174 | |||
175 | std::vector<Layer> changedLayers; | ||
176 | std::vector<IComposerClient::Composition> compositionTypes; | ||
177 | uint32_t displayRequestMask = 0; | ||
178 | std::vector<Layer> requestedLayers; | ||
179 | std::vector<uint32_t> requestMasks; | ||
180 | mHal.validateDisplay(dpy.first, &changedLayers, &compositionTypes, | ||
181 | &displayRequestMask, &requestedLayers, &requestMasks); | ||
182 | |||
183 | mHal.acceptDisplayChanges(dpy.first); | ||
184 | |||
185 | int32_t presentFence = -1; | ||
186 | std::vector<Layer> releasedLayers; | ||
187 | std::vector<int32_t> releaseFences; | ||
188 | mHal.presentDisplay(dpy.first, &presentFence, &releasedLayers, &releaseFences); | ||
189 | if (presentFence >= 0) { | ||
190 | close(presentFence); | ||
191 | } | ||
192 | for (auto fence : releaseFences) { | ||
193 | if (fence >= 0) { | ||
194 | close(fence); | ||
195 | } | ||
196 | } | ||
197 | } | ||
198 | } | ||
199 | |||
200 | mDisplayData.clear(); | ||
201 | |||
202 | sHandleImporter.cleanup(); | ||
203 | |||
204 | mHal.removeClient(); | ||
205 | |||
206 | ALOGW("removed composer client"); | ||
207 | } | ||
208 | |||
209 | void ComposerClient::initialize() | ||
210 | { | ||
211 | mReader = createCommandReader(); | ||
212 | if (!sHandleImporter.initialize()) { | ||
213 | LOG_ALWAYS_FATAL("failed to initialize handle importer"); | ||
214 | } | ||
215 | } | ||
216 | |||
217 | void ComposerClient::onHotplug(Display display, | ||
218 | IComposerCallback::Connection connected) | ||
219 | { | ||
220 | { | ||
221 | std::lock_guard<std::mutex> lock(mDisplayDataMutex); | ||
222 | |||
223 | if (connected == IComposerCallback::Connection::CONNECTED) { | ||
224 | mDisplayData.emplace(display, DisplayData(false)); | ||
225 | } else if (connected == IComposerCallback::Connection::DISCONNECTED) { | ||
226 | mDisplayData.erase(display); | ||
227 | } | ||
228 | } | ||
229 | |||
230 | auto ret = mCallback->onHotplug(display, connected); | ||
231 | ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s", | ||
232 | ret.description().c_str()); | ||
233 | } | ||
234 | |||
235 | void ComposerClient::onRefresh(Display display) | ||
236 | { | ||
237 | auto ret = mCallback->onRefresh(display); | ||
238 | ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s", | ||
239 | ret.description().c_str()); | ||
240 | } | ||
241 | |||
242 | void ComposerClient::onVsync(Display display, int64_t timestamp) | ||
243 | { | ||
244 | auto ret = mCallback->onVsync(display, timestamp); | ||
245 | ALOGE_IF(!ret.isOk(), "failed to send onVsync: %s", | ||
246 | ret.description().c_str()); | ||
247 | } | ||
248 | |||
249 | Return<void> ComposerClient::registerCallback( | ||
250 | const sp<IComposerCallback>& callback) | ||
251 | { | ||
252 | // no locking as we require this function to be called only once | ||
253 | mCallback = callback; | ||
254 | mHal.enableCallback(callback != nullptr); | ||
255 | |||
256 | return Void(); | ||
257 | } | ||
258 | |||
259 | Return<uint32_t> ComposerClient::getMaxVirtualDisplayCount() | ||
260 | { | ||
261 | return mHal.getMaxVirtualDisplayCount(); | ||
262 | } | ||
263 | |||
264 | Return<void> ComposerClient::createVirtualDisplay(uint32_t width, | ||
265 | uint32_t height, PixelFormat formatHint, uint32_t outputBufferSlotCount, | ||
266 | createVirtualDisplay_cb hidl_cb) | ||
267 | { | ||
268 | Display display = 0; | ||
269 | Error err = mHal.createVirtualDisplay(width, height, | ||
270 | &formatHint, &display); | ||
271 | if (err == Error::NONE) { | ||
272 | std::lock_guard<std::mutex> lock(mDisplayDataMutex); | ||
273 | |||
274 | auto dpy = mDisplayData.emplace(display, DisplayData(true)).first; | ||
275 | dpy->second.OutputBuffers.resize(outputBufferSlotCount); | ||
276 | } | ||
277 | |||
278 | hidl_cb(err, display, formatHint); | ||
279 | return Void(); | ||
280 | } | ||
281 | |||
282 | Return<Error> ComposerClient::destroyVirtualDisplay(Display display) | ||
283 | { | ||
284 | Error err = mHal.destroyVirtualDisplay(display); | ||
285 | if (err == Error::NONE) { | ||
286 | std::lock_guard<std::mutex> lock(mDisplayDataMutex); | ||
287 | |||
288 | mDisplayData.erase(display); | ||
289 | } | ||
290 | |||
291 | return err; | ||
292 | } | ||
293 | |||
294 | Return<void> ComposerClient::createLayer(Display display, | ||
295 | uint32_t bufferSlotCount, createLayer_cb hidl_cb) | ||
296 | { | ||
297 | Layer layer = 0; | ||
298 | Error err = mHal.createLayer(display, &layer); | ||
299 | if (err == Error::NONE) { | ||
300 | std::lock_guard<std::mutex> lock(mDisplayDataMutex); | ||
301 | auto dpy = mDisplayData.find(display); | ||
302 | // The display entry may have already been removed by onHotplug. | ||
303 | if (dpy != mDisplayData.end()) { | ||
304 | auto ly = dpy->second.Layers.emplace(layer, LayerBuffers()).first; | ||
305 | ly->second.Buffers.resize(bufferSlotCount); | ||
306 | } else { | ||
307 | err = Error::BAD_DISPLAY; | ||
308 | // Note: We do not destroy the layer on this error as the hotplug | ||
309 | // disconnect invalidates the display id. The implementation should | ||
310 | // ensure all layers for the display are destroyed. | ||
311 | } | ||
312 | } | ||
313 | |||
314 | hidl_cb(err, layer); | ||
315 | return Void(); | ||
316 | } | ||
317 | |||
318 | Return<Error> ComposerClient::destroyLayer(Display display, Layer layer) | ||
319 | { | ||
320 | Error err = mHal.destroyLayer(display, layer); | ||
321 | if (err == Error::NONE) { | ||
322 | std::lock_guard<std::mutex> lock(mDisplayDataMutex); | ||
323 | |||
324 | auto dpy = mDisplayData.find(display); | ||
325 | // The display entry may have already been removed by onHotplug. | ||
326 | if (dpy != mDisplayData.end()) { | ||
327 | dpy->second.Layers.erase(layer); | ||
328 | } | ||
329 | } | ||
330 | |||
331 | return err; | ||
332 | } | ||
333 | |||
334 | Return<void> ComposerClient::getActiveConfig(Display display, | ||
335 | getActiveConfig_cb hidl_cb) | ||
336 | { | ||
337 | Config config = 0; | ||
338 | Error err = mHal.getActiveConfig(display, &config); | ||
339 | |||
340 | hidl_cb(err, config); | ||
341 | return Void(); | ||
342 | } | ||
343 | |||
344 | Return<Error> ComposerClient::getClientTargetSupport(Display display, | ||
345 | uint32_t width, uint32_t height, | ||
346 | PixelFormat format, Dataspace dataspace) | ||
347 | { | ||
348 | Error err = mHal.getClientTargetSupport(display, | ||
349 | width, height, format, dataspace); | ||
350 | return err; | ||
351 | } | ||
352 | |||
353 | Return<void> ComposerClient::getColorModes(Display display, | ||
354 | getColorModes_cb hidl_cb) | ||
355 | { | ||
356 | hidl_vec<ColorMode> modes; | ||
357 | Error err = mHal.getColorModes(display, &modes); | ||
358 | |||
359 | hidl_cb(err, modes); | ||
360 | return Void(); | ||
361 | } | ||
362 | |||
363 | Return<void> ComposerClient::getDisplayAttribute(Display display, | ||
364 | Config config, Attribute attribute, | ||
365 | getDisplayAttribute_cb hidl_cb) | ||
366 | { | ||
367 | int32_t value = 0; | ||
368 | Error err = mHal.getDisplayAttribute(display, config, attribute, &value); | ||
369 | |||
370 | hidl_cb(err, value); | ||
371 | return Void(); | ||
372 | } | ||
373 | |||
374 | Return<void> ComposerClient::getDisplayConfigs(Display display, | ||
375 | getDisplayConfigs_cb hidl_cb) | ||
376 | { | ||
377 | hidl_vec<Config> configs; | ||
378 | Error err = mHal.getDisplayConfigs(display, &configs); | ||
379 | |||
380 | hidl_cb(err, configs); | ||
381 | return Void(); | ||
382 | } | ||
383 | |||
384 | Return<void> ComposerClient::getDisplayName(Display display, | ||
385 | getDisplayName_cb hidl_cb) | ||
386 | { | ||
387 | hidl_string name; | ||
388 | Error err = mHal.getDisplayName(display, &name); | ||
389 | |||
390 | hidl_cb(err, name); | ||
391 | return Void(); | ||
392 | } | ||
393 | |||
394 | Return<void> ComposerClient::getDisplayType(Display display, | ||
395 | getDisplayType_cb hidl_cb) | ||
396 | { | ||
397 | DisplayType type = DisplayType::INVALID; | ||
398 | Error err = mHal.getDisplayType(display, &type); | ||
399 | |||
400 | hidl_cb(err, type); | ||
401 | return Void(); | ||
402 | } | ||
403 | |||
404 | Return<void> ComposerClient::getDozeSupport(Display display, | ||
405 | getDozeSupport_cb hidl_cb) | ||
406 | { | ||
407 | bool support = false; | ||
408 | Error err = mHal.getDozeSupport(display, &support); | ||
409 | |||
410 | hidl_cb(err, support); | ||
411 | return Void(); | ||
412 | } | ||
413 | |||
414 | Return<void> ComposerClient::getHdrCapabilities(Display display, | ||
415 | getHdrCapabilities_cb hidl_cb) | ||
416 | { | ||
417 | hidl_vec<Hdr> types; | ||
418 | float max_lumi = 0.0f; | ||
419 | float max_avg_lumi = 0.0f; | ||
420 | float min_lumi = 0.0f; | ||
421 | Error err = mHal.getHdrCapabilities(display, &types, | ||
422 | &max_lumi, &max_avg_lumi, &min_lumi); | ||
423 | |||
424 | hidl_cb(err, types, max_lumi, max_avg_lumi, min_lumi); | ||
425 | return Void(); | ||
426 | } | ||
427 | |||
428 | Return<Error> ComposerClient::setClientTargetSlotCount(Display display, | ||
429 | uint32_t clientTargetSlotCount) | ||
430 | { | ||
431 | std::lock_guard<std::mutex> lock(mDisplayDataMutex); | ||
432 | |||
433 | auto dpy = mDisplayData.find(display); | ||
434 | if (dpy == mDisplayData.end()) { | ||
435 | return Error::BAD_DISPLAY; | ||
436 | } | ||
437 | |||
438 | dpy->second.ClientTargets.resize(clientTargetSlotCount); | ||
439 | |||
440 | return Error::NONE; | ||
441 | } | ||
442 | |||
443 | Return<Error> ComposerClient::setActiveConfig(Display display, Config config) | ||
444 | { | ||
445 | Error err = mHal.setActiveConfig(display, config); | ||
446 | return err; | ||
447 | } | ||
448 | |||
449 | Return<Error> ComposerClient::setColorMode(Display display, ColorMode mode) | ||
450 | { | ||
451 | Error err = mHal.setColorMode(display, mode); | ||
452 | return err; | ||
453 | } | ||
454 | |||
455 | Return<Error> ComposerClient::setPowerMode(Display display, PowerMode mode) | ||
456 | { | ||
457 | Error err = mHal.setPowerMode(display, mode); | ||
458 | return err; | ||
459 | } | ||
460 | |||
461 | Return<Error> ComposerClient::setVsyncEnabled(Display display, Vsync enabled) | ||
462 | { | ||
463 | Error err = mHal.setVsyncEnabled(display, enabled); | ||
464 | return err; | ||
465 | } | ||
466 | |||
467 | Return<Error> ComposerClient::setInputCommandQueue( | ||
468 | const MQDescriptorSync<uint32_t>& descriptor) | ||
469 | { | ||
470 | std::lock_guard<std::mutex> lock(mCommandMutex); | ||
471 | return mReader->setMQDescriptor(descriptor) ? | ||
472 | Error::NONE : Error::NO_RESOURCES; | ||
473 | } | ||
474 | |||
475 | Return<void> ComposerClient::getOutputCommandQueue( | ||
476 | getOutputCommandQueue_cb hidl_cb) | ||
477 | { | ||
478 | // no locking as we require this function to be called inside | ||
479 | // executeCommands_cb | ||
480 | |||
481 | auto outDescriptor = mWriter.getMQDescriptor(); | ||
482 | if (outDescriptor) { | ||
483 | hidl_cb(Error::NONE, *outDescriptor); | ||
484 | } else { | ||
485 | hidl_cb(Error::NO_RESOURCES, CommandQueueType::Descriptor()); | ||
486 | } | ||
487 | |||
488 | return Void(); | ||
489 | } | ||
490 | |||
491 | Return<void> ComposerClient::executeCommands(uint32_t inLength, | ||
492 | const hidl_vec<hidl_handle>& inHandles, | ||
493 | executeCommands_cb hidl_cb) | ||
494 | { | ||
495 | std::lock_guard<std::mutex> lock(mCommandMutex); | ||
496 | |||
497 | bool outChanged = false; | ||
498 | uint32_t outLength = 0; | ||
499 | hidl_vec<hidl_handle> outHandles; | ||
500 | |||
501 | if (!mReader->readQueue(inLength, inHandles)) { | ||
502 | hidl_cb(Error::BAD_PARAMETER, outChanged, outLength, outHandles); | ||
503 | return Void(); | ||
504 | } | ||
505 | |||
506 | Error err = mReader->parse(); | ||
507 | if (err == Error::NONE && | ||
508 | !mWriter.writeQueue(&outChanged, &outLength, &outHandles)) { | ||
509 | err = Error::NO_RESOURCES; | ||
510 | } | ||
511 | |||
512 | hidl_cb(err, outChanged, outLength, outHandles); | ||
513 | |||
514 | mReader->reset(); | ||
515 | mWriter.reset(); | ||
516 | |||
517 | return Void(); | ||
518 | } | ||
519 | |||
520 | std::unique_ptr<ComposerClient::CommandReader> | ||
521 | ComposerClient::createCommandReader() | ||
522 | { | ||
523 | return std::unique_ptr<ComposerClient::CommandReader>( | ||
524 | new CommandReader(*this)); | ||
525 | } | ||
526 | |||
527 | ComposerClient::CommandReader::CommandReader(ComposerClient& client) | ||
528 | : mClient(client), mHal(client.mHal), mWriter(client.mWriter) | ||
529 | { | ||
530 | } | ||
531 | |||
532 | ComposerClient::CommandReader::~CommandReader() | ||
533 | { | ||
534 | } | ||
535 | |||
536 | Error ComposerClient::CommandReader::parse() | ||
537 | { | ||
538 | IComposerClient::Command command; | ||
539 | uint16_t length = 0; | ||
540 | |||
541 | while (!isEmpty()) { | ||
542 | if (!beginCommand(&command, &length)) { | ||
543 | break; | ||
544 | } | ||
545 | |||
546 | bool parsed = parseCommand(command, length); | ||
547 | endCommand(); | ||
548 | |||
549 | if (!parsed) { | ||
550 | ALOGE("failed to parse command 0x%x, length %" PRIu16, | ||
551 | command, length); | ||
552 | break; | ||
553 | } | ||
554 | } | ||
555 | |||
556 | return (isEmpty()) ? Error::NONE : Error::BAD_PARAMETER; | ||
557 | } | ||
558 | |||
559 | bool ComposerClient::CommandReader::parseCommand( | ||
560 | IComposerClient::Command command, uint16_t length) { | ||
561 | switch (command) { | ||
562 | case IComposerClient::Command::SELECT_DISPLAY: | ||
563 | return parseSelectDisplay(length); | ||
564 | case IComposerClient::Command::SELECT_LAYER: | ||
565 | return parseSelectLayer(length); | ||
566 | case IComposerClient::Command::SET_COLOR_TRANSFORM: | ||
567 | return parseSetColorTransform(length); | ||
568 | case IComposerClient::Command::SET_CLIENT_TARGET: | ||
569 | return parseSetClientTarget(length); | ||
570 | case IComposerClient::Command::SET_OUTPUT_BUFFER: | ||
571 | return parseSetOutputBuffer(length); | ||
572 | case IComposerClient::Command::VALIDATE_DISPLAY: | ||
573 | return parseValidateDisplay(length); | ||
574 | case IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY: | ||
575 | return parsePresentOrValidateDisplay(length); | ||
576 | case IComposerClient::Command::ACCEPT_DISPLAY_CHANGES: | ||
577 | return parseAcceptDisplayChanges(length); | ||
578 | case IComposerClient::Command::PRESENT_DISPLAY: | ||
579 | return parsePresentDisplay(length); | ||
580 | case IComposerClient::Command::SET_LAYER_CURSOR_POSITION: | ||
581 | return parseSetLayerCursorPosition(length); | ||
582 | case IComposerClient::Command::SET_LAYER_BUFFER: | ||
583 | return parseSetLayerBuffer(length); | ||
584 | case IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE: | ||
585 | return parseSetLayerSurfaceDamage(length); | ||
586 | case IComposerClient::Command::SET_LAYER_BLEND_MODE: | ||
587 | return parseSetLayerBlendMode(length); | ||
588 | case IComposerClient::Command::SET_LAYER_COLOR: | ||
589 | return parseSetLayerColor(length); | ||
590 | case IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE: | ||
591 | return parseSetLayerCompositionType(length); | ||
592 | case IComposerClient::Command::SET_LAYER_DATASPACE: | ||
593 | return parseSetLayerDataspace(length); | ||
594 | case IComposerClient::Command::SET_LAYER_DISPLAY_FRAME: | ||
595 | return parseSetLayerDisplayFrame(length); | ||
596 | case IComposerClient::Command::SET_LAYER_PLANE_ALPHA: | ||
597 | return parseSetLayerPlaneAlpha(length); | ||
598 | case IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM: | ||
599 | return parseSetLayerSidebandStream(length); | ||
600 | case IComposerClient::Command::SET_LAYER_SOURCE_CROP: | ||
601 | return parseSetLayerSourceCrop(length); | ||
602 | case IComposerClient::Command::SET_LAYER_TRANSFORM: | ||
603 | return parseSetLayerTransform(length); | ||
604 | case IComposerClient::Command::SET_LAYER_VISIBLE_REGION: | ||
605 | return parseSetLayerVisibleRegion(length); | ||
606 | case IComposerClient::Command::SET_LAYER_Z_ORDER: | ||
607 | return parseSetLayerZOrder(length); | ||
608 | default: | ||
609 | return false; | ||
610 | } | ||
611 | } | ||
612 | |||
613 | bool ComposerClient::CommandReader::parseSelectDisplay(uint16_t length) | ||
614 | { | ||
615 | if (length != CommandWriterBase::kSelectDisplayLength) { | ||
616 | return false; | ||
617 | } | ||
618 | |||
619 | mDisplay = read64(); | ||
620 | mWriter.selectDisplay(mDisplay); | ||
621 | |||
622 | return true; | ||
623 | } | ||
624 | |||
625 | bool ComposerClient::CommandReader::parseSelectLayer(uint16_t length) | ||
626 | { | ||
627 | if (length != CommandWriterBase::kSelectLayerLength) { | ||
628 | return false; | ||
629 | } | ||
630 | |||
631 | mLayer = read64(); | ||
632 | |||
633 | return true; | ||
634 | } | ||
635 | |||
636 | bool ComposerClient::CommandReader::parseSetColorTransform(uint16_t length) | ||
637 | { | ||
638 | if (length != CommandWriterBase::kSetColorTransformLength) { | ||
639 | return false; | ||
640 | } | ||
641 | |||
642 | float matrix[16]; | ||
643 | for (int i = 0; i < 16; i++) { | ||
644 | matrix[i] = readFloat(); | ||
645 | } | ||
646 | auto transform = readSigned(); | ||
647 | |||
648 | auto err = mHal.setColorTransform(mDisplay, matrix, transform); | ||
649 | if (err != Error::NONE) { | ||
650 | mWriter.setError(getCommandLoc(), err); | ||
651 | } | ||
652 | |||
653 | return true; | ||
654 | } | ||
655 | |||
656 | bool ComposerClient::CommandReader::parseSetClientTarget(uint16_t length) | ||
657 | { | ||
658 | // 4 parameters followed by N rectangles | ||
659 | if ((length - 4) % 4 != 0) { | ||
660 | return false; | ||
661 | } | ||
662 | |||
663 | bool useCache = false; | ||
664 | auto slot = read(); | ||
665 | auto clientTarget = readHandle(&useCache); | ||
666 | auto fence = readFence(); | ||
667 | auto dataspace = readSigned(); | ||
668 | auto damage = readRegion((length - 4) / 4); | ||
669 | bool closeFence = true; | ||
670 | |||
671 | auto err = lookupBuffer(BufferCache::CLIENT_TARGETS, | ||
672 | slot, useCache, clientTarget, &clientTarget); | ||
673 | if (err == Error::NONE) { | ||
674 | err = mHal.setClientTarget(mDisplay, clientTarget, fence, | ||
675 | dataspace, damage); | ||
676 | auto updateBufErr = updateBuffer(BufferCache::CLIENT_TARGETS, slot, | ||
677 | useCache, clientTarget); | ||
678 | if (err == Error::NONE) { | ||
679 | closeFence = false; | ||
680 | err = updateBufErr; | ||
681 | } | ||
682 | } | ||
683 | if (closeFence) { | ||
684 | close(fence); | ||
685 | } | ||
686 | if (err != Error::NONE) { | ||
687 | mWriter.setError(getCommandLoc(), err); | ||
688 | } | ||
689 | |||
690 | return true; | ||
691 | } | ||
692 | |||
693 | bool ComposerClient::CommandReader::parseSetOutputBuffer(uint16_t length) | ||
694 | { | ||
695 | if (length != CommandWriterBase::kSetOutputBufferLength) { | ||
696 | return false; | ||
697 | } | ||
698 | |||
699 | bool useCache = false; | ||
700 | auto slot = read(); | ||
701 | auto outputBuffer = readHandle(&useCache); | ||
702 | auto fence = readFence(); | ||
703 | bool closeFence = true; | ||
704 | |||
705 | auto err = lookupBuffer(BufferCache::OUTPUT_BUFFERS, | ||
706 | slot, useCache, outputBuffer, &outputBuffer); | ||
707 | if (err == Error::NONE) { | ||
708 | err = mHal.setOutputBuffer(mDisplay, outputBuffer, fence); | ||
709 | auto updateBufErr = updateBuffer(BufferCache::OUTPUT_BUFFERS, | ||
710 | slot, useCache, outputBuffer); | ||
711 | if (err == Error::NONE) { | ||
712 | closeFence = false; | ||
713 | err = updateBufErr; | ||
714 | } | ||
715 | } | ||
716 | if (closeFence) { | ||
717 | close(fence); | ||
718 | } | ||
719 | if (err != Error::NONE) { | ||
720 | mWriter.setError(getCommandLoc(), err); | ||
721 | } | ||
722 | |||
723 | return true; | ||
724 | } | ||
725 | |||
726 | bool ComposerClient::CommandReader::parseValidateDisplay(uint16_t length) | ||
727 | { | ||
728 | if (length != CommandWriterBase::kValidateDisplayLength) { | ||
729 | return false; | ||
730 | } | ||
731 | |||
732 | std::vector<Layer> changedLayers; | ||
733 | std::vector<IComposerClient::Composition> compositionTypes; | ||
734 | uint32_t displayRequestMask = 0x0; | ||
735 | std::vector<Layer> requestedLayers; | ||
736 | std::vector<uint32_t> requestMasks; | ||
737 | |||
738 | auto err = mHal.validateDisplay(mDisplay, &changedLayers, | ||
739 | &compositionTypes, &displayRequestMask, | ||
740 | &requestedLayers, &requestMasks); | ||
741 | if (err == Error::NONE) { | ||
742 | mWriter.setChangedCompositionTypes(changedLayers, | ||
743 | compositionTypes); | ||
744 | mWriter.setDisplayRequests(displayRequestMask, | ||
745 | requestedLayers, requestMasks); | ||
746 | } else { | ||
747 | mWriter.setError(getCommandLoc(), err); | ||
748 | } | ||
749 | |||
750 | return true; | ||
751 | } | ||
752 | |||
753 | bool ComposerClient::CommandReader::parsePresentOrValidateDisplay(uint16_t length) | ||
754 | { | ||
755 | if (length != CommandWriterBase::kPresentOrValidateDisplayLength) { | ||
756 | return false; | ||
757 | } | ||
758 | |||
759 | // First try to Present as is. | ||
760 | if (mHal.hasCapability(HWC2_CAPABILITY_SKIP_VALIDATE)) { | ||
761 | int presentFence = -1; | ||
762 | std::vector<Layer> layers; | ||
763 | std::vector<int> fences; | ||
764 | auto err = mHal.presentDisplay(mDisplay, &presentFence, &layers, &fences); | ||
765 | if (err == Error::NONE) { | ||
766 | mWriter.setPresentOrValidateResult(1); | ||
767 | mWriter.setPresentFence(presentFence); | ||
768 | mWriter.setReleaseFences(layers, fences); | ||
769 | return true; | ||
770 | } | ||
771 | } | ||
772 | |||
773 | // Present has failed. We need to fallback to validate | ||
774 | std::vector<Layer> changedLayers; | ||
775 | std::vector<IComposerClient::Composition> compositionTypes; | ||
776 | uint32_t displayRequestMask = 0x0; | ||
777 | std::vector<Layer> requestedLayers; | ||
778 | std::vector<uint32_t> requestMasks; | ||
779 | |||
780 | auto err = mHal.validateDisplay(mDisplay, &changedLayers, &compositionTypes, | ||
781 | &displayRequestMask, &requestedLayers, &requestMasks); | ||
782 | if (err == Error::NONE) { | ||
783 | mWriter.setPresentOrValidateResult(0); | ||
784 | mWriter.setChangedCompositionTypes(changedLayers, | ||
785 | compositionTypes); | ||
786 | mWriter.setDisplayRequests(displayRequestMask, | ||
787 | requestedLayers, requestMasks); | ||
788 | } else { | ||
789 | mWriter.setError(getCommandLoc(), err); | ||
790 | } | ||
791 | |||
792 | return true; | ||
793 | } | ||
794 | |||
795 | bool ComposerClient::CommandReader::parseAcceptDisplayChanges(uint16_t length) | ||
796 | { | ||
797 | if (length != CommandWriterBase::kAcceptDisplayChangesLength) { | ||
798 | return false; | ||
799 | } | ||
800 | |||
801 | auto err = mHal.acceptDisplayChanges(mDisplay); | ||
802 | if (err != Error::NONE) { | ||
803 | mWriter.setError(getCommandLoc(), err); | ||
804 | } | ||
805 | |||
806 | return true; | ||
807 | } | ||
808 | |||
809 | bool ComposerClient::CommandReader::parsePresentDisplay(uint16_t length) | ||
810 | { | ||
811 | if (length != CommandWriterBase::kPresentDisplayLength) { | ||
812 | return false; | ||
813 | } | ||
814 | |||
815 | int presentFence = -1; | ||
816 | std::vector<Layer> layers; | ||
817 | std::vector<int> fences; | ||
818 | auto err = mHal.presentDisplay(mDisplay, &presentFence, &layers, &fences); | ||
819 | if (err == Error::NONE) { | ||
820 | mWriter.setPresentFence(presentFence); | ||
821 | mWriter.setReleaseFences(layers, fences); | ||
822 | } else { | ||
823 | mWriter.setError(getCommandLoc(), err); | ||
824 | } | ||
825 | |||
826 | return true; | ||
827 | } | ||
828 | |||
829 | bool ComposerClient::CommandReader::parseSetLayerCursorPosition(uint16_t length) | ||
830 | { | ||
831 | if (length != CommandWriterBase::kSetLayerCursorPositionLength) { | ||
832 | return false; | ||
833 | } | ||
834 | |||
835 | auto err = mHal.setLayerCursorPosition(mDisplay, mLayer, | ||
836 | readSigned(), readSigned()); | ||
837 | if (err != Error::NONE) { | ||
838 | mWriter.setError(getCommandLoc(), err); | ||
839 | } | ||
840 | |||
841 | return true; | ||
842 | } | ||
843 | |||
844 | bool ComposerClient::CommandReader::parseSetLayerBuffer(uint16_t length) | ||
845 | { | ||
846 | if (length != CommandWriterBase::kSetLayerBufferLength) { | ||
847 | return false; | ||
848 | } | ||
849 | |||
850 | bool useCache = false; | ||
851 | auto slot = read(); | ||
852 | auto buffer = readHandle(&useCache); | ||
853 | auto fence = readFence(); | ||
854 | bool closeFence = true; | ||
855 | |||
856 | auto err = lookupBuffer(BufferCache::LAYER_BUFFERS, | ||
857 | slot, useCache, buffer, &buffer); | ||
858 | if (err == Error::NONE) { | ||
859 | err = mHal.setLayerBuffer(mDisplay, mLayer, buffer, fence); | ||
860 | auto updateBufErr = updateBuffer(BufferCache::LAYER_BUFFERS, slot, | ||
861 | useCache, buffer); | ||
862 | if (err == Error::NONE) { | ||
863 | closeFence = false; | ||
864 | err = updateBufErr; | ||
865 | } | ||
866 | } | ||
867 | if (closeFence) { | ||
868 | close(fence); | ||
869 | } | ||
870 | if (err != Error::NONE) { | ||
871 | mWriter.setError(getCommandLoc(), err); | ||
872 | } | ||
873 | |||
874 | return true; | ||
875 | } | ||
876 | |||
877 | bool ComposerClient::CommandReader::parseSetLayerSurfaceDamage(uint16_t length) | ||
878 | { | ||
879 | // N rectangles | ||
880 | if (length % 4 != 0) { | ||
881 | return false; | ||
882 | } | ||
883 | |||
884 | auto damage = readRegion(length / 4); | ||
885 | auto err = mHal.setLayerSurfaceDamage(mDisplay, mLayer, damage); | ||
886 | if (err != Error::NONE) { | ||
887 | mWriter.setError(getCommandLoc(), err); | ||
888 | } | ||
889 | |||
890 | return true; | ||
891 | } | ||
892 | |||
893 | bool ComposerClient::CommandReader::parseSetLayerBlendMode(uint16_t length) | ||
894 | { | ||
895 | if (length != CommandWriterBase::kSetLayerBlendModeLength) { | ||
896 | return false; | ||
897 | } | ||
898 | |||
899 | auto err = mHal.setLayerBlendMode(mDisplay, mLayer, readSigned()); | ||
900 | if (err != Error::NONE) { | ||
901 | mWriter.setError(getCommandLoc(), err); | ||
902 | } | ||
903 | |||
904 | return true; | ||
905 | } | ||
906 | |||
907 | bool ComposerClient::CommandReader::parseSetLayerColor(uint16_t length) | ||
908 | { | ||
909 | if (length != CommandWriterBase::kSetLayerColorLength) { | ||
910 | return false; | ||
911 | } | ||
912 | |||
913 | auto err = mHal.setLayerColor(mDisplay, mLayer, readColor()); | ||
914 | if (err != Error::NONE) { | ||
915 | mWriter.setError(getCommandLoc(), err); | ||
916 | } | ||
917 | |||
918 | return true; | ||
919 | } | ||
920 | |||
921 | bool ComposerClient::CommandReader::parseSetLayerCompositionType( | ||
922 | uint16_t length) | ||
923 | { | ||
924 | if (length != CommandWriterBase::kSetLayerCompositionTypeLength) { | ||
925 | return false; | ||
926 | } | ||
927 | |||
928 | auto err = mHal.setLayerCompositionType(mDisplay, mLayer, readSigned()); | ||
929 | if (err != Error::NONE) { | ||
930 | mWriter.setError(getCommandLoc(), err); | ||
931 | } | ||
932 | |||
933 | return true; | ||
934 | } | ||
935 | |||
936 | bool ComposerClient::CommandReader::parseSetLayerDataspace(uint16_t length) | ||
937 | { | ||
938 | if (length != CommandWriterBase::kSetLayerDataspaceLength) { | ||
939 | return false; | ||
940 | } | ||
941 | |||
942 | auto err = mHal.setLayerDataspace(mDisplay, mLayer, readSigned()); | ||
943 | if (err != Error::NONE) { | ||
944 | mWriter.setError(getCommandLoc(), err); | ||
945 | } | ||
946 | |||
947 | return true; | ||
948 | } | ||
949 | |||
950 | bool ComposerClient::CommandReader::parseSetLayerDisplayFrame(uint16_t length) | ||
951 | { | ||
952 | if (length != CommandWriterBase::kSetLayerDisplayFrameLength) { | ||
953 | return false; | ||
954 | } | ||
955 | |||
956 | auto err = mHal.setLayerDisplayFrame(mDisplay, mLayer, readRect()); | ||
957 | if (err != Error::NONE) { | ||
958 | mWriter.setError(getCommandLoc(), err); | ||
959 | } | ||
960 | |||
961 | return true; | ||
962 | } | ||
963 | |||
964 | bool ComposerClient::CommandReader::parseSetLayerPlaneAlpha(uint16_t length) | ||
965 | { | ||
966 | if (length != CommandWriterBase::kSetLayerPlaneAlphaLength) { | ||
967 | return false; | ||
968 | } | ||
969 | |||
970 | auto err = mHal.setLayerPlaneAlpha(mDisplay, mLayer, readFloat()); | ||
971 | if (err != Error::NONE) { | ||
972 | mWriter.setError(getCommandLoc(), err); | ||
973 | } | ||
974 | |||
975 | return true; | ||
976 | } | ||
977 | |||
978 | bool ComposerClient::CommandReader::parseSetLayerSidebandStream(uint16_t length) | ||
979 | { | ||
980 | if (length != CommandWriterBase::kSetLayerSidebandStreamLength) { | ||
981 | return false; | ||
982 | } | ||
983 | |||
984 | auto stream = readHandle(); | ||
985 | |||
986 | auto err = lookupLayerSidebandStream(stream, &stream); | ||
987 | if (err == Error::NONE) { | ||
988 | err = mHal.setLayerSidebandStream(mDisplay, mLayer, stream); | ||
989 | auto updateErr = updateLayerSidebandStream(stream); | ||
990 | if (err == Error::NONE) { | ||
991 | err = updateErr; | ||
992 | } | ||
993 | } | ||
994 | if (err != Error::NONE) { | ||
995 | mWriter.setError(getCommandLoc(), err); | ||
996 | } | ||
997 | |||
998 | return true; | ||
999 | } | ||
1000 | |||
1001 | bool ComposerClient::CommandReader::parseSetLayerSourceCrop(uint16_t length) | ||
1002 | { | ||
1003 | if (length != CommandWriterBase::kSetLayerSourceCropLength) { | ||
1004 | return false; | ||
1005 | } | ||
1006 | |||
1007 | auto err = mHal.setLayerSourceCrop(mDisplay, mLayer, readFRect()); | ||
1008 | if (err != Error::NONE) { | ||
1009 | mWriter.setError(getCommandLoc(), err); | ||
1010 | } | ||
1011 | |||
1012 | return true; | ||
1013 | } | ||
1014 | |||
1015 | bool ComposerClient::CommandReader::parseSetLayerTransform(uint16_t length) | ||
1016 | { | ||
1017 | if (length != CommandWriterBase::kSetLayerTransformLength) { | ||
1018 | return false; | ||
1019 | } | ||
1020 | |||
1021 | auto err = mHal.setLayerTransform(mDisplay, mLayer, readSigned()); | ||
1022 | if (err != Error::NONE) { | ||
1023 | mWriter.setError(getCommandLoc(), err); | ||
1024 | } | ||
1025 | |||
1026 | return true; | ||
1027 | } | ||
1028 | |||
1029 | bool ComposerClient::CommandReader::parseSetLayerVisibleRegion(uint16_t length) | ||
1030 | { | ||
1031 | // N rectangles | ||
1032 | if (length % 4 != 0) { | ||
1033 | return false; | ||
1034 | } | ||
1035 | |||
1036 | auto region = readRegion(length / 4); | ||
1037 | auto err = mHal.setLayerVisibleRegion(mDisplay, mLayer, region); | ||
1038 | if (err != Error::NONE) { | ||
1039 | mWriter.setError(getCommandLoc(), err); | ||
1040 | } | ||
1041 | |||
1042 | return true; | ||
1043 | } | ||
1044 | |||
1045 | bool ComposerClient::CommandReader::parseSetLayerZOrder(uint16_t length) | ||
1046 | { | ||
1047 | if (length != CommandWriterBase::kSetLayerZOrderLength) { | ||
1048 | return false; | ||
1049 | } | ||
1050 | |||
1051 | auto err = mHal.setLayerZOrder(mDisplay, mLayer, read()); | ||
1052 | if (err != Error::NONE) { | ||
1053 | mWriter.setError(getCommandLoc(), err); | ||
1054 | } | ||
1055 | |||
1056 | return true; | ||
1057 | } | ||
1058 | |||
1059 | hwc_rect_t ComposerClient::CommandReader::readRect() | ||
1060 | { | ||
1061 | return hwc_rect_t{ | ||
1062 | readSigned(), | ||
1063 | readSigned(), | ||
1064 | readSigned(), | ||
1065 | readSigned(), | ||
1066 | }; | ||
1067 | } | ||
1068 | |||
1069 | std::vector<hwc_rect_t> ComposerClient::CommandReader::readRegion(size_t count) | ||
1070 | { | ||
1071 | std::vector<hwc_rect_t> region; | ||
1072 | region.reserve(count); | ||
1073 | while (count > 0) { | ||
1074 | region.emplace_back(readRect()); | ||
1075 | count--; | ||
1076 | } | ||
1077 | |||
1078 | return region; | ||
1079 | } | ||
1080 | |||
1081 | hwc_frect_t ComposerClient::CommandReader::readFRect() | ||
1082 | { | ||
1083 | return hwc_frect_t{ | ||
1084 | readFloat(), | ||
1085 | readFloat(), | ||
1086 | readFloat(), | ||
1087 | readFloat(), | ||
1088 | }; | ||
1089 | } | ||
1090 | |||
1091 | Error ComposerClient::CommandReader::lookupBufferCacheEntryLocked( | ||
1092 | BufferCache cache, uint32_t slot, BufferCacheEntry** outEntry) | ||
1093 | { | ||
1094 | auto dpy = mClient.mDisplayData.find(mDisplay); | ||
1095 | if (dpy == mClient.mDisplayData.end()) { | ||
1096 | return Error::BAD_DISPLAY; | ||
1097 | } | ||
1098 | |||
1099 | BufferCacheEntry* entry = nullptr; | ||
1100 | switch (cache) { | ||
1101 | case BufferCache::CLIENT_TARGETS: | ||
1102 | if (slot < dpy->second.ClientTargets.size()) { | ||
1103 | entry = &dpy->second.ClientTargets[slot]; | ||
1104 | } | ||
1105 | break; | ||
1106 | case BufferCache::OUTPUT_BUFFERS: | ||
1107 | if (slot < dpy->second.OutputBuffers.size()) { | ||
1108 | entry = &dpy->second.OutputBuffers[slot]; | ||
1109 | } | ||
1110 | break; | ||
1111 | case BufferCache::LAYER_BUFFERS: | ||
1112 | { | ||
1113 | auto ly = dpy->second.Layers.find(mLayer); | ||
1114 | if (ly == dpy->second.Layers.end()) { | ||
1115 | return Error::BAD_LAYER; | ||
1116 | } | ||
1117 | if (slot < ly->second.Buffers.size()) { | ||
1118 | entry = &ly->second.Buffers[slot]; | ||
1119 | } | ||
1120 | } | ||
1121 | break; | ||
1122 | case BufferCache::LAYER_SIDEBAND_STREAMS: | ||
1123 | { | ||
1124 | auto ly = dpy->second.Layers.find(mLayer); | ||
1125 | if (ly == dpy->second.Layers.end()) { | ||
1126 | return Error::BAD_LAYER; | ||
1127 | } | ||
1128 | if (slot == 0) { | ||
1129 | entry = &ly->second.SidebandStream; | ||
1130 | } | ||
1131 | } | ||
1132 | break; | ||
1133 | default: | ||
1134 | break; | ||
1135 | } | ||
1136 | |||
1137 | if (!entry) { | ||
1138 | ALOGW("invalid buffer slot %" PRIu32, slot); | ||
1139 | return Error::BAD_PARAMETER; | ||
1140 | } | ||
1141 | |||
1142 | *outEntry = entry; | ||
1143 | |||
1144 | return Error::NONE; | ||
1145 | } | ||
1146 | |||
1147 | Error ComposerClient::CommandReader::lookupBuffer(BufferCache cache, | ||
1148 | uint32_t slot, bool useCache, buffer_handle_t handle, | ||
1149 | buffer_handle_t* outHandle) | ||
1150 | { | ||
1151 | if (useCache) { | ||
1152 | std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex); | ||
1153 | |||
1154 | BufferCacheEntry* entry; | ||
1155 | Error error = lookupBufferCacheEntryLocked(cache, slot, &entry); | ||
1156 | if (error != Error::NONE) { | ||
1157 | return error; | ||
1158 | } | ||
1159 | |||
1160 | // input handle is ignored | ||
1161 | *outHandle = entry->getHandle(); | ||
1162 | } else if (cache == BufferCache::LAYER_SIDEBAND_STREAMS) { | ||
1163 | if (handle) { | ||
1164 | *outHandle = native_handle_clone(handle); | ||
1165 | if (*outHandle == nullptr) { | ||
1166 | return Error::NO_RESOURCES; | ||
1167 | } | ||
1168 | } | ||
1169 | } else { | ||
1170 | if (!sHandleImporter.importBuffer(handle)) { | ||
1171 | return Error::NO_RESOURCES; | ||
1172 | } | ||
1173 | |||
1174 | *outHandle = handle; | ||
1175 | } | ||
1176 | |||
1177 | return Error::NONE; | ||
1178 | } | ||
1179 | |||
1180 | Error ComposerClient::CommandReader::updateBuffer(BufferCache cache, | ||
1181 | uint32_t slot, bool useCache, buffer_handle_t handle) | ||
1182 | { | ||
1183 | // handle was looked up from cache | ||
1184 | if (useCache) { | ||
1185 | return Error::NONE; | ||
1186 | } | ||
1187 | |||
1188 | std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex); | ||
1189 | |||
1190 | BufferCacheEntry* entry = nullptr; | ||
1191 | Error error = lookupBufferCacheEntryLocked(cache, slot, &entry); | ||
1192 | if (error != Error::NONE) { | ||
1193 | return error; | ||
1194 | } | ||
1195 | |||
1196 | *entry = handle; | ||
1197 | return Error::NONE; | ||
1198 | } | ||
1199 | |||
1200 | } // namespace implementation | ||
1201 | } // namespace V2_1 | ||
1202 | } // namespace composer | ||
1203 | } // namespace graphics | ||
1204 | } // namespace hardware | ||
1205 | } // namespace android | ||
diff --git a/graphics/composer/2.1/default/ComposerClient.h b/graphics/composer/2.1/default/ComposerClient.h deleted file mode 100644 index 104ed5af..00000000 --- a/graphics/composer/2.1/default/ComposerClient.h +++ /dev/null | |||
@@ -1,225 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H | ||
18 | #define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H | ||
19 | |||
20 | #include <mutex> | ||
21 | #include <unordered_map> | ||
22 | #include <vector> | ||
23 | |||
24 | #include <composer-command-buffer/2.1/ComposerCommandBuffer.h> | ||
25 | #include <hardware/hwcomposer2.h> | ||
26 | #include "ComposerBase.h" | ||
27 | |||
28 | namespace android { | ||
29 | namespace hardware { | ||
30 | namespace graphics { | ||
31 | namespace composer { | ||
32 | namespace V2_1 { | ||
33 | namespace implementation { | ||
34 | |||
35 | class BufferCacheEntry { | ||
36 | public: | ||
37 | BufferCacheEntry(); | ||
38 | BufferCacheEntry(BufferCacheEntry&& other); | ||
39 | |||
40 | BufferCacheEntry(const BufferCacheEntry& other) = delete; | ||
41 | BufferCacheEntry& operator=(const BufferCacheEntry& other) = delete; | ||
42 | |||
43 | BufferCacheEntry& operator=(buffer_handle_t handle); | ||
44 | ~BufferCacheEntry(); | ||
45 | |||
46 | buffer_handle_t getHandle() const { return mHandle; } | ||
47 | |||
48 | private: | ||
49 | void clear(); | ||
50 | |||
51 | buffer_handle_t mHandle; | ||
52 | }; | ||
53 | |||
54 | class ComposerClient : public IComposerClient { | ||
55 | public: | ||
56 | ComposerClient(ComposerBase& hal); | ||
57 | virtual ~ComposerClient(); | ||
58 | |||
59 | void initialize(); | ||
60 | |||
61 | void onHotplug(Display display, IComposerCallback::Connection connected); | ||
62 | void onRefresh(Display display); | ||
63 | void onVsync(Display display, int64_t timestamp); | ||
64 | |||
65 | // IComposerClient interface | ||
66 | Return<void> registerCallback( | ||
67 | const sp<IComposerCallback>& callback) override; | ||
68 | Return<uint32_t> getMaxVirtualDisplayCount() override; | ||
69 | Return<void> createVirtualDisplay(uint32_t width, uint32_t height, | ||
70 | PixelFormat formatHint, uint32_t outputBufferSlotCount, | ||
71 | createVirtualDisplay_cb hidl_cb) override; | ||
72 | Return<Error> destroyVirtualDisplay(Display display) override; | ||
73 | Return<void> createLayer(Display display, uint32_t bufferSlotCount, | ||
74 | createLayer_cb hidl_cb) override; | ||
75 | Return<Error> destroyLayer(Display display, Layer layer) override; | ||
76 | Return<void> getActiveConfig(Display display, | ||
77 | getActiveConfig_cb hidl_cb) override; | ||
78 | Return<Error> getClientTargetSupport(Display display, | ||
79 | uint32_t width, uint32_t height, | ||
80 | PixelFormat format, Dataspace dataspace) override; | ||
81 | Return<void> getColorModes(Display display, | ||
82 | getColorModes_cb hidl_cb) override; | ||
83 | Return<void> getDisplayAttribute(Display display, | ||
84 | Config config, Attribute attribute, | ||
85 | getDisplayAttribute_cb hidl_cb) override; | ||
86 | Return<void> getDisplayConfigs(Display display, | ||
87 | getDisplayConfigs_cb hidl_cb) override; | ||
88 | Return<void> getDisplayName(Display display, | ||
89 | getDisplayName_cb hidl_cb) override; | ||
90 | Return<void> getDisplayType(Display display, | ||
91 | getDisplayType_cb hidl_cb) override; | ||
92 | Return<void> getDozeSupport(Display display, | ||
93 | getDozeSupport_cb hidl_cb) override; | ||
94 | Return<void> getHdrCapabilities(Display display, | ||
95 | getHdrCapabilities_cb hidl_cb) override; | ||
96 | Return<Error> setActiveConfig(Display display, Config config) override; | ||
97 | Return<Error> setColorMode(Display display, ColorMode mode) override; | ||
98 | Return<Error> setPowerMode(Display display, PowerMode mode) override; | ||
99 | Return<Error> setVsyncEnabled(Display display, Vsync enabled) override; | ||
100 | Return<Error> setClientTargetSlotCount(Display display, | ||
101 | uint32_t clientTargetSlotCount) override; | ||
102 | Return<Error> setInputCommandQueue( | ||
103 | const MQDescriptorSync<uint32_t>& descriptor) override; | ||
104 | Return<void> getOutputCommandQueue( | ||
105 | getOutputCommandQueue_cb hidl_cb) override; | ||
106 | Return<void> executeCommands(uint32_t inLength, | ||
107 | const hidl_vec<hidl_handle>& inHandles, | ||
108 | executeCommands_cb hidl_cb) override; | ||
109 | |||
110 | protected: | ||
111 | struct LayerBuffers { | ||
112 | std::vector<BufferCacheEntry> Buffers; | ||
113 | // the handle is a sideband stream handle, not a buffer handle | ||
114 | BufferCacheEntry SidebandStream; | ||
115 | }; | ||
116 | |||
117 | struct DisplayData { | ||
118 | bool IsVirtual; | ||
119 | |||
120 | std::vector<BufferCacheEntry> ClientTargets; | ||
121 | std::vector<BufferCacheEntry> OutputBuffers; | ||
122 | |||
123 | std::unordered_map<Layer, LayerBuffers> Layers; | ||
124 | |||
125 | DisplayData(bool isVirtual) : IsVirtual(isVirtual) {} | ||
126 | }; | ||
127 | |||
128 | class CommandReader : public CommandReaderBase { | ||
129 | public: | ||
130 | CommandReader(ComposerClient& client); | ||
131 | virtual ~CommandReader(); | ||
132 | |||
133 | Error parse(); | ||
134 | |||
135 | protected: | ||
136 | virtual bool parseCommand(IComposerClient::Command command, | ||
137 | uint16_t length); | ||
138 | |||
139 | bool parseSelectDisplay(uint16_t length); | ||
140 | bool parseSelectLayer(uint16_t length); | ||
141 | bool parseSetColorTransform(uint16_t length); | ||
142 | bool parseSetClientTarget(uint16_t length); | ||
143 | bool parseSetOutputBuffer(uint16_t length); | ||
144 | bool parseValidateDisplay(uint16_t length); | ||
145 | bool parsePresentOrValidateDisplay(uint16_t length); | ||
146 | bool parseAcceptDisplayChanges(uint16_t length); | ||
147 | bool parsePresentDisplay(uint16_t length); | ||
148 | bool parseSetLayerCursorPosition(uint16_t length); | ||
149 | bool parseSetLayerBuffer(uint16_t length); | ||
150 | bool parseSetLayerSurfaceDamage(uint16_t length); | ||
151 | bool parseSetLayerBlendMode(uint16_t length); | ||
152 | bool parseSetLayerColor(uint16_t length); | ||
153 | bool parseSetLayerCompositionType(uint16_t length); | ||
154 | bool parseSetLayerDataspace(uint16_t length); | ||
155 | bool parseSetLayerDisplayFrame(uint16_t length); | ||
156 | bool parseSetLayerPlaneAlpha(uint16_t length); | ||
157 | bool parseSetLayerSidebandStream(uint16_t length); | ||
158 | bool parseSetLayerSourceCrop(uint16_t length); | ||
159 | bool parseSetLayerTransform(uint16_t length); | ||
160 | bool parseSetLayerVisibleRegion(uint16_t length); | ||
161 | bool parseSetLayerZOrder(uint16_t length); | ||
162 | |||
163 | hwc_rect_t readRect(); | ||
164 | std::vector<hwc_rect_t> readRegion(size_t count); | ||
165 | hwc_frect_t readFRect(); | ||
166 | |||
167 | enum class BufferCache { | ||
168 | CLIENT_TARGETS, | ||
169 | OUTPUT_BUFFERS, | ||
170 | LAYER_BUFFERS, | ||
171 | LAYER_SIDEBAND_STREAMS, | ||
172 | }; | ||
173 | Error lookupBufferCacheEntryLocked(BufferCache cache, uint32_t slot, | ||
174 | BufferCacheEntry** outEntry); | ||
175 | Error lookupBuffer(BufferCache cache, uint32_t slot, | ||
176 | bool useCache, buffer_handle_t handle, | ||
177 | buffer_handle_t* outHandle); | ||
178 | Error updateBuffer(BufferCache cache, uint32_t slot, | ||
179 | bool useCache, buffer_handle_t handle); | ||
180 | |||
181 | Error lookupLayerSidebandStream(buffer_handle_t handle, | ||
182 | buffer_handle_t* outHandle) | ||
183 | { | ||
184 | return lookupBuffer(BufferCache::LAYER_SIDEBAND_STREAMS, | ||
185 | 0, false, handle, outHandle); | ||
186 | } | ||
187 | Error updateLayerSidebandStream(buffer_handle_t handle) | ||
188 | { | ||
189 | return updateBuffer(BufferCache::LAYER_SIDEBAND_STREAMS, | ||
190 | 0, false, handle); | ||
191 | } | ||
192 | |||
193 | ComposerClient& mClient; | ||
194 | ComposerBase& mHal; | ||
195 | CommandWriterBase& mWriter; | ||
196 | |||
197 | Display mDisplay; | ||
198 | Layer mLayer; | ||
199 | }; | ||
200 | |||
201 | virtual std::unique_ptr<CommandReader> createCommandReader(); | ||
202 | |||
203 | ComposerBase& mHal; | ||
204 | |||
205 | // 64KiB minus a small space for metadata such as read/write pointers | ||
206 | static constexpr size_t kWriterInitialSize = | ||
207 | 64 * 1024 / sizeof(uint32_t) - 16; | ||
208 | std::mutex mCommandMutex; | ||
209 | std::unique_ptr<CommandReader> mReader; | ||
210 | CommandWriterBase mWriter; | ||
211 | |||
212 | sp<IComposerCallback> mCallback; | ||
213 | |||
214 | std::mutex mDisplayDataMutex; | ||
215 | std::unordered_map<Display, DisplayData> mDisplayData; | ||
216 | }; | ||
217 | |||
218 | } // namespace implementation | ||
219 | } // namespace V2_1 | ||
220 | } // namespace composer | ||
221 | } // namespace graphics | ||
222 | } // namespace hardware | ||
223 | } // namespace android | ||
224 | |||
225 | #endif // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H | ||
diff --git a/graphics/composer/2.1/default/Hwc.cpp b/graphics/composer/2.1/default/Hwc.cpp deleted file mode 100644 index cb393eca..00000000 --- a/graphics/composer/2.1/default/Hwc.cpp +++ /dev/null | |||
@@ -1,817 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #define LOG_TAG "HwcPassthrough" | ||
18 | |||
19 | #include "Hwc.h" | ||
20 | |||
21 | #include <chrono> | ||
22 | #include <type_traits> | ||
23 | #include <log/log.h> | ||
24 | |||
25 | #include "ComposerClient.h" | ||
26 | #include "hardware/fb.h" | ||
27 | #include "hardware/hwcomposer.h" | ||
28 | #include "hwc2on1adapter/HWC2On1Adapter.h" | ||
29 | #include "hwc2onfbadapter/HWC2OnFbAdapter.h" | ||
30 | |||
31 | using namespace std::chrono_literals; | ||
32 | |||
33 | namespace android { | ||
34 | namespace hardware { | ||
35 | namespace graphics { | ||
36 | namespace composer { | ||
37 | namespace V2_1 { | ||
38 | namespace implementation { | ||
39 | |||
40 | HwcHal::HwcHal(const hw_module_t* module) | ||
41 | : mDevice(nullptr), mDispatch(), mMustValidateDisplay(true), mAdapter() { | ||
42 | uint32_t majorVersion; | ||
43 | if (module->id && strcmp(module->id, GRALLOC_HARDWARE_MODULE_ID) == 0) { | ||
44 | majorVersion = initWithFb(module); | ||
45 | } else { | ||
46 | majorVersion = initWithHwc(module); | ||
47 | } | ||
48 | |||
49 | initCapabilities(); | ||
50 | if (majorVersion >= 2 && hasCapability(HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE)) { | ||
51 | ALOGE("Present fence must be reliable from HWC2 on."); | ||
52 | abort(); | ||
53 | } | ||
54 | |||
55 | initDispatch(); | ||
56 | } | ||
57 | |||
58 | HwcHal::~HwcHal() | ||
59 | { | ||
60 | hwc2_close(mDevice); | ||
61 | } | ||
62 | |||
63 | uint32_t HwcHal::initWithHwc(const hw_module_t* module) | ||
64 | { | ||
65 | // Determine what kind of module is available (HWC2 vs HWC1.X). | ||
66 | hw_device_t* device = nullptr; | ||
67 | int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device); | ||
68 | if (error != 0) { | ||
69 | ALOGE("Failed to open HWC device (%s), aborting", strerror(-error)); | ||
70 | abort(); | ||
71 | } | ||
72 | uint32_t majorVersion = (device->version >> 24) & 0xF; | ||
73 | |||
74 | // If we don't have a HWC2, we need to wrap whatever we have in an adapter. | ||
75 | if (majorVersion != 2) { | ||
76 | uint32_t minorVersion = device->version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK; | ||
77 | minorVersion = (minorVersion >> 16) & 0xF; | ||
78 | ALOGI("Found HWC implementation v%d.%d", majorVersion, minorVersion); | ||
79 | if (minorVersion < 1) { | ||
80 | ALOGE("Cannot adapt to HWC version %d.%d. Minimum supported is 1.1", | ||
81 | majorVersion, minorVersion); | ||
82 | abort(); | ||
83 | } | ||
84 | mAdapter = std::make_unique<HWC2On1Adapter>( | ||
85 | reinterpret_cast<hwc_composer_device_1*>(device)); | ||
86 | |||
87 | // Place the adapter in front of the device module. | ||
88 | mDevice = mAdapter.get(); | ||
89 | } else { | ||
90 | mDevice = reinterpret_cast<hwc2_device_t*>(device); | ||
91 | } | ||
92 | |||
93 | return majorVersion; | ||
94 | } | ||
95 | |||
96 | uint32_t HwcHal::initWithFb(const hw_module_t* module) | ||
97 | { | ||
98 | framebuffer_device_t* fb_device; | ||
99 | int error = framebuffer_open(module, &fb_device); | ||
100 | if (error != 0) { | ||
101 | ALOGE("Failed to open FB device (%s), aborting", strerror(-error)); | ||
102 | abort(); | ||
103 | } | ||
104 | |||
105 | mFbAdapter = std::make_unique<HWC2OnFbAdapter>(fb_device); | ||
106 | mDevice = mFbAdapter.get(); | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | void HwcHal::initCapabilities() | ||
112 | { | ||
113 | uint32_t count = 0; | ||
114 | mDevice->getCapabilities(mDevice, &count, nullptr); | ||
115 | |||
116 | std::vector<int32_t> caps(count); | ||
117 | mDevice->getCapabilities(mDevice, &count, caps.data()); | ||
118 | caps.resize(count); | ||
119 | |||
120 | mCapabilities.reserve(count); | ||
121 | for (auto cap : caps) { | ||
122 | mCapabilities.insert(static_cast<hwc2_capability_t>(cap)); | ||
123 | } | ||
124 | } | ||
125 | |||
126 | template<typename T> | ||
127 | void HwcHal::initDispatch(hwc2_function_descriptor_t desc, T* outPfn) | ||
128 | { | ||
129 | auto pfn = mDevice->getFunction(mDevice, desc); | ||
130 | if (!pfn) { | ||
131 | LOG_ALWAYS_FATAL("failed to get hwcomposer2 function %d", desc); | ||
132 | } | ||
133 | |||
134 | *outPfn = reinterpret_cast<T>(pfn); | ||
135 | } | ||
136 | |||
137 | void HwcHal::initDispatch() | ||
138 | { | ||
139 | initDispatch(HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES, | ||
140 | &mDispatch.acceptDisplayChanges); | ||
141 | initDispatch(HWC2_FUNCTION_CREATE_LAYER, &mDispatch.createLayer); | ||
142 | initDispatch(HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY, | ||
143 | &mDispatch.createVirtualDisplay); | ||
144 | initDispatch(HWC2_FUNCTION_DESTROY_LAYER, &mDispatch.destroyLayer); | ||
145 | initDispatch(HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY, | ||
146 | &mDispatch.destroyVirtualDisplay); | ||
147 | initDispatch(HWC2_FUNCTION_DUMP, &mDispatch.dump); | ||
148 | initDispatch(HWC2_FUNCTION_GET_ACTIVE_CONFIG, &mDispatch.getActiveConfig); | ||
149 | initDispatch(HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES, | ||
150 | &mDispatch.getChangedCompositionTypes); | ||
151 | initDispatch(HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT, | ||
152 | &mDispatch.getClientTargetSupport); | ||
153 | initDispatch(HWC2_FUNCTION_GET_COLOR_MODES, &mDispatch.getColorModes); | ||
154 | initDispatch(HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE, | ||
155 | &mDispatch.getDisplayAttribute); | ||
156 | initDispatch(HWC2_FUNCTION_GET_DISPLAY_CONFIGS, | ||
157 | &mDispatch.getDisplayConfigs); | ||
158 | initDispatch(HWC2_FUNCTION_GET_DISPLAY_NAME, &mDispatch.getDisplayName); | ||
159 | initDispatch(HWC2_FUNCTION_GET_DISPLAY_REQUESTS, | ||
160 | &mDispatch.getDisplayRequests); | ||
161 | initDispatch(HWC2_FUNCTION_GET_DISPLAY_TYPE, &mDispatch.getDisplayType); | ||
162 | initDispatch(HWC2_FUNCTION_GET_DOZE_SUPPORT, &mDispatch.getDozeSupport); | ||
163 | initDispatch(HWC2_FUNCTION_GET_HDR_CAPABILITIES, | ||
164 | &mDispatch.getHdrCapabilities); | ||
165 | initDispatch(HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT, | ||
166 | &mDispatch.getMaxVirtualDisplayCount); | ||
167 | initDispatch(HWC2_FUNCTION_GET_RELEASE_FENCES, | ||
168 | &mDispatch.getReleaseFences); | ||
169 | initDispatch(HWC2_FUNCTION_PRESENT_DISPLAY, &mDispatch.presentDisplay); | ||
170 | initDispatch(HWC2_FUNCTION_REGISTER_CALLBACK, | ||
171 | &mDispatch.registerCallback); | ||
172 | initDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG, &mDispatch.setActiveConfig); | ||
173 | initDispatch(HWC2_FUNCTION_SET_CLIENT_TARGET, &mDispatch.setClientTarget); | ||
174 | initDispatch(HWC2_FUNCTION_SET_COLOR_MODE, &mDispatch.setColorMode); | ||
175 | initDispatch(HWC2_FUNCTION_SET_COLOR_TRANSFORM, | ||
176 | &mDispatch.setColorTransform); | ||
177 | initDispatch(HWC2_FUNCTION_SET_CURSOR_POSITION, | ||
178 | &mDispatch.setCursorPosition); | ||
179 | initDispatch(HWC2_FUNCTION_SET_LAYER_BLEND_MODE, | ||
180 | &mDispatch.setLayerBlendMode); | ||
181 | initDispatch(HWC2_FUNCTION_SET_LAYER_BUFFER, &mDispatch.setLayerBuffer); | ||
182 | initDispatch(HWC2_FUNCTION_SET_LAYER_COLOR, &mDispatch.setLayerColor); | ||
183 | initDispatch(HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE, | ||
184 | &mDispatch.setLayerCompositionType); | ||
185 | initDispatch(HWC2_FUNCTION_SET_LAYER_DATASPACE, | ||
186 | &mDispatch.setLayerDataspace); | ||
187 | initDispatch(HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME, | ||
188 | &mDispatch.setLayerDisplayFrame); | ||
189 | initDispatch(HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA, | ||
190 | &mDispatch.setLayerPlaneAlpha); | ||
191 | |||
192 | if (hasCapability(HWC2_CAPABILITY_SIDEBAND_STREAM)) { | ||
193 | initDispatch(HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM, | ||
194 | &mDispatch.setLayerSidebandStream); | ||
195 | } | ||
196 | |||
197 | initDispatch(HWC2_FUNCTION_SET_LAYER_SOURCE_CROP, | ||
198 | &mDispatch.setLayerSourceCrop); | ||
199 | initDispatch(HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE, | ||
200 | &mDispatch.setLayerSurfaceDamage); | ||
201 | initDispatch(HWC2_FUNCTION_SET_LAYER_TRANSFORM, | ||
202 | &mDispatch.setLayerTransform); | ||
203 | initDispatch(HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION, | ||
204 | &mDispatch.setLayerVisibleRegion); | ||
205 | initDispatch(HWC2_FUNCTION_SET_LAYER_Z_ORDER, &mDispatch.setLayerZOrder); | ||
206 | initDispatch(HWC2_FUNCTION_SET_OUTPUT_BUFFER, &mDispatch.setOutputBuffer); | ||
207 | initDispatch(HWC2_FUNCTION_SET_POWER_MODE, &mDispatch.setPowerMode); | ||
208 | initDispatch(HWC2_FUNCTION_SET_VSYNC_ENABLED, &mDispatch.setVsyncEnabled); | ||
209 | initDispatch(HWC2_FUNCTION_VALIDATE_DISPLAY, &mDispatch.validateDisplay); | ||
210 | } | ||
211 | |||
212 | bool HwcHal::hasCapability(hwc2_capability_t capability) { | ||
213 | return (mCapabilities.count(capability) > 0); | ||
214 | } | ||
215 | |||
216 | Return<void> HwcHal::getCapabilities(getCapabilities_cb hidl_cb) | ||
217 | { | ||
218 | std::vector<Capability> caps; | ||
219 | caps.reserve(mCapabilities.size()); | ||
220 | for (auto cap : mCapabilities) { | ||
221 | switch (cap) { | ||
222 | case HWC2_CAPABILITY_SIDEBAND_STREAM: | ||
223 | case HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM: | ||
224 | case HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE: | ||
225 | caps.push_back(static_cast<Capability>(cap)); | ||
226 | break; | ||
227 | default: | ||
228 | // not all HWC2 caps are defined in HIDL | ||
229 | break; | ||
230 | } | ||
231 | } | ||
232 | |||
233 | hidl_vec<Capability> caps_reply; | ||
234 | caps_reply.setToExternal(caps.data(), caps.size()); | ||
235 | hidl_cb(caps_reply); | ||
236 | |||
237 | return Void(); | ||
238 | } | ||
239 | |||
240 | Return<void> HwcHal::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) | ||
241 | { | ||
242 | uint32_t len = 0; | ||
243 | mDispatch.dump(mDevice, &len, nullptr); | ||
244 | |||
245 | std::vector<char> buf(len + 1); | ||
246 | mDispatch.dump(mDevice, &len, buf.data()); | ||
247 | buf.resize(len + 1); | ||
248 | buf[len] = '\0'; | ||
249 | |||
250 | hidl_string buf_reply; | ||
251 | buf_reply.setToExternal(buf.data(), len); | ||
252 | hidl_cb(buf_reply); | ||
253 | |||
254 | return Void(); | ||
255 | } | ||
256 | |||
257 | Return<void> HwcHal::createClient(createClient_cb hidl_cb) | ||
258 | { | ||
259 | Error err = Error::NONE; | ||
260 | sp<ComposerClient> client; | ||
261 | |||
262 | { | ||
263 | std::unique_lock<std::mutex> lock(mClientMutex); | ||
264 | |||
265 | if (mClient != nullptr) { | ||
266 | // In surface flinger we delete a composer client on one thread and | ||
267 | // then create a new client on another thread. Although surface | ||
268 | // flinger ensures the calls are made in that sequence (destroy and | ||
269 | // then create), sometimes the calls land in the composer service | ||
270 | // inverted (create and then destroy). Wait for a brief period to | ||
271 | // see if the existing client is destroyed. | ||
272 | ALOGI("HwcHal::createClient: Client already exists. Waiting for" | ||
273 | " it to be destroyed."); | ||
274 | mClientDestroyedWait.wait_for(lock, 1s, | ||
275 | [this] { return mClient == nullptr; }); | ||
276 | std::string doneMsg = mClient == nullptr ? | ||
277 | "Existing client was destroyed." : | ||
278 | "Existing client was never destroyed!"; | ||
279 | ALOGI("HwcHal::createClient: Done waiting. %s", doneMsg.c_str()); | ||
280 | } | ||
281 | |||
282 | // only one client is allowed | ||
283 | if (mClient == nullptr) { | ||
284 | client = new ComposerClient(*this); | ||
285 | client->initialize(); | ||
286 | mClient = client; | ||
287 | } else { | ||
288 | err = Error::NO_RESOURCES; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | hidl_cb(err, client); | ||
293 | |||
294 | return Void(); | ||
295 | } | ||
296 | |||
297 | sp<ComposerClient> HwcHal::getClient() | ||
298 | { | ||
299 | std::lock_guard<std::mutex> lock(mClientMutex); | ||
300 | return (mClient != nullptr) ? mClient.promote() : nullptr; | ||
301 | } | ||
302 | |||
303 | void HwcHal::removeClient() | ||
304 | { | ||
305 | std::lock_guard<std::mutex> lock(mClientMutex); | ||
306 | mClient = nullptr; | ||
307 | mClientDestroyedWait.notify_all(); | ||
308 | } | ||
309 | |||
310 | void HwcHal::hotplugHook(hwc2_callback_data_t callbackData, | ||
311 | hwc2_display_t display, int32_t connected) | ||
312 | { | ||
313 | auto hal = reinterpret_cast<HwcHal*>(callbackData); | ||
314 | auto client = hal->getClient(); | ||
315 | if (client != nullptr) { | ||
316 | client->onHotplug(display, | ||
317 | static_cast<IComposerCallback::Connection>(connected)); | ||
318 | } | ||
319 | } | ||
320 | |||
321 | void HwcHal::refreshHook(hwc2_callback_data_t callbackData, | ||
322 | hwc2_display_t display) | ||
323 | { | ||
324 | auto hal = reinterpret_cast<HwcHal*>(callbackData); | ||
325 | hal->mMustValidateDisplay = true; | ||
326 | |||
327 | auto client = hal->getClient(); | ||
328 | if (client != nullptr) { | ||
329 | client->onRefresh(display); | ||
330 | } | ||
331 | } | ||
332 | |||
333 | void HwcHal::vsyncHook(hwc2_callback_data_t callbackData, | ||
334 | hwc2_display_t display, int64_t timestamp) | ||
335 | { | ||
336 | auto hal = reinterpret_cast<HwcHal*>(callbackData); | ||
337 | auto client = hal->getClient(); | ||
338 | if (client != nullptr) { | ||
339 | client->onVsync(display, timestamp); | ||
340 | } | ||
341 | } | ||
342 | |||
343 | void HwcHal::enableCallback(bool enable) | ||
344 | { | ||
345 | if (enable) { | ||
346 | mMustValidateDisplay = true; | ||
347 | |||
348 | mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, | ||
349 | reinterpret_cast<hwc2_function_pointer_t>(hotplugHook)); | ||
350 | mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this, | ||
351 | reinterpret_cast<hwc2_function_pointer_t>(refreshHook)); | ||
352 | mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this, | ||
353 | reinterpret_cast<hwc2_function_pointer_t>(vsyncHook)); | ||
354 | } else { | ||
355 | mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, | ||
356 | nullptr); | ||
357 | mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this, | ||
358 | nullptr); | ||
359 | mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this, | ||
360 | nullptr); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | uint32_t HwcHal::getMaxVirtualDisplayCount() | ||
365 | { | ||
366 | return mDispatch.getMaxVirtualDisplayCount(mDevice); | ||
367 | } | ||
368 | |||
369 | Error HwcHal::createVirtualDisplay(uint32_t width, uint32_t height, | ||
370 | PixelFormat* format, Display* outDisplay) | ||
371 | { | ||
372 | int32_t hwc_format = static_cast<int32_t>(*format); | ||
373 | int32_t err = mDispatch.createVirtualDisplay(mDevice, width, height, | ||
374 | &hwc_format, outDisplay); | ||
375 | *format = static_cast<PixelFormat>(hwc_format); | ||
376 | |||
377 | return static_cast<Error>(err); | ||
378 | } | ||
379 | |||
380 | Error HwcHal::destroyVirtualDisplay(Display display) | ||
381 | { | ||
382 | int32_t err = mDispatch.destroyVirtualDisplay(mDevice, display); | ||
383 | return static_cast<Error>(err); | ||
384 | } | ||
385 | |||
386 | Error HwcHal::createLayer(Display display, Layer* outLayer) | ||
387 | { | ||
388 | int32_t err = mDispatch.createLayer(mDevice, display, outLayer); | ||
389 | return static_cast<Error>(err); | ||
390 | } | ||
391 | |||
392 | Error HwcHal::destroyLayer(Display display, Layer layer) | ||
393 | { | ||
394 | int32_t err = mDispatch.destroyLayer(mDevice, display, layer); | ||
395 | return static_cast<Error>(err); | ||
396 | } | ||
397 | |||
398 | Error HwcHal::getActiveConfig(Display display, Config* outConfig) | ||
399 | { | ||
400 | int32_t err = mDispatch.getActiveConfig(mDevice, display, outConfig); | ||
401 | return static_cast<Error>(err); | ||
402 | } | ||
403 | |||
404 | Error HwcHal::getClientTargetSupport(Display display, | ||
405 | uint32_t width, uint32_t height, | ||
406 | PixelFormat format, Dataspace dataspace) | ||
407 | { | ||
408 | int32_t err = mDispatch.getClientTargetSupport(mDevice, display, | ||
409 | width, height, static_cast<int32_t>(format), | ||
410 | static_cast<int32_t>(dataspace)); | ||
411 | return static_cast<Error>(err); | ||
412 | } | ||
413 | |||
414 | Error HwcHal::getColorModes(Display display, hidl_vec<ColorMode>* outModes) | ||
415 | { | ||
416 | uint32_t count = 0; | ||
417 | int32_t err = mDispatch.getColorModes(mDevice, display, &count, nullptr); | ||
418 | if (err != HWC2_ERROR_NONE) { | ||
419 | return static_cast<Error>(err); | ||
420 | } | ||
421 | |||
422 | outModes->resize(count); | ||
423 | err = mDispatch.getColorModes(mDevice, display, &count, | ||
424 | reinterpret_cast<std::underlying_type<ColorMode>::type*>( | ||
425 | outModes->data())); | ||
426 | if (err != HWC2_ERROR_NONE) { | ||
427 | *outModes = hidl_vec<ColorMode>(); | ||
428 | return static_cast<Error>(err); | ||
429 | } | ||
430 | |||
431 | return Error::NONE; | ||
432 | } | ||
433 | |||
434 | Error HwcHal::getDisplayAttribute(Display display, Config config, | ||
435 | IComposerClient::Attribute attribute, int32_t* outValue) | ||
436 | { | ||
437 | int32_t err = mDispatch.getDisplayAttribute(mDevice, display, config, | ||
438 | static_cast<int32_t>(attribute), outValue); | ||
439 | return static_cast<Error>(err); | ||
440 | } | ||
441 | |||
442 | Error HwcHal::getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs) | ||
443 | { | ||
444 | uint32_t count = 0; | ||
445 | int32_t err = mDispatch.getDisplayConfigs(mDevice, display, | ||
446 | &count, nullptr); | ||
447 | if (err != HWC2_ERROR_NONE) { | ||
448 | return static_cast<Error>(err); | ||
449 | } | ||
450 | |||
451 | outConfigs->resize(count); | ||
452 | err = mDispatch.getDisplayConfigs(mDevice, display, | ||
453 | &count, outConfigs->data()); | ||
454 | if (err != HWC2_ERROR_NONE) { | ||
455 | *outConfigs = hidl_vec<Config>(); | ||
456 | return static_cast<Error>(err); | ||
457 | } | ||
458 | |||
459 | return Error::NONE; | ||
460 | } | ||
461 | |||
462 | Error HwcHal::getDisplayName(Display display, hidl_string* outName) | ||
463 | { | ||
464 | uint32_t count = 0; | ||
465 | int32_t err = mDispatch.getDisplayName(mDevice, display, &count, nullptr); | ||
466 | if (err != HWC2_ERROR_NONE) { | ||
467 | return static_cast<Error>(err); | ||
468 | } | ||
469 | |||
470 | std::vector<char> buf(count + 1); | ||
471 | err = mDispatch.getDisplayName(mDevice, display, &count, buf.data()); | ||
472 | if (err != HWC2_ERROR_NONE) { | ||
473 | return static_cast<Error>(err); | ||
474 | } | ||
475 | buf.resize(count + 1); | ||
476 | buf[count] = '\0'; | ||
477 | |||
478 | *outName = buf.data(); | ||
479 | |||
480 | return Error::NONE; | ||
481 | } | ||
482 | |||
483 | Error HwcHal::getDisplayType(Display display, | ||
484 | IComposerClient::DisplayType* outType) | ||
485 | { | ||
486 | int32_t hwc_type = HWC2_DISPLAY_TYPE_INVALID; | ||
487 | int32_t err = mDispatch.getDisplayType(mDevice, display, &hwc_type); | ||
488 | *outType = static_cast<IComposerClient::DisplayType>(hwc_type); | ||
489 | |||
490 | return static_cast<Error>(err); | ||
491 | } | ||
492 | |||
493 | Error HwcHal::getDozeSupport(Display display, bool* outSupport) | ||
494 | { | ||
495 | int32_t hwc_support = 0; | ||
496 | int32_t err = mDispatch.getDozeSupport(mDevice, display, &hwc_support); | ||
497 | *outSupport = hwc_support; | ||
498 | |||
499 | return static_cast<Error>(err); | ||
500 | } | ||
501 | |||
502 | Error HwcHal::getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes, | ||
503 | float* outMaxLuminance, float* outMaxAverageLuminance, | ||
504 | float* outMinLuminance) | ||
505 | { | ||
506 | uint32_t count = 0; | ||
507 | int32_t err = mDispatch.getHdrCapabilities(mDevice, display, &count, | ||
508 | nullptr, outMaxLuminance, outMaxAverageLuminance, | ||
509 | outMinLuminance); | ||
510 | if (err != HWC2_ERROR_NONE) { | ||
511 | return static_cast<Error>(err); | ||
512 | } | ||
513 | |||
514 | outTypes->resize(count); | ||
515 | err = mDispatch.getHdrCapabilities(mDevice, display, &count, | ||
516 | reinterpret_cast<std::underlying_type<Hdr>::type*>( | ||
517 | outTypes->data()), outMaxLuminance, | ||
518 | outMaxAverageLuminance, outMinLuminance); | ||
519 | if (err != HWC2_ERROR_NONE) { | ||
520 | *outTypes = hidl_vec<Hdr>(); | ||
521 | return static_cast<Error>(err); | ||
522 | } | ||
523 | |||
524 | return Error::NONE; | ||
525 | } | ||
526 | |||
527 | Error HwcHal::setActiveConfig(Display display, Config config) | ||
528 | { | ||
529 | int32_t err = mDispatch.setActiveConfig(mDevice, display, config); | ||
530 | return static_cast<Error>(err); | ||
531 | } | ||
532 | |||
533 | Error HwcHal::setColorMode(Display display, ColorMode mode) | ||
534 | { | ||
535 | int32_t err = mDispatch.setColorMode(mDevice, display, | ||
536 | static_cast<int32_t>(mode)); | ||
537 | return static_cast<Error>(err); | ||
538 | } | ||
539 | |||
540 | Error HwcHal::setPowerMode(Display display, IComposerClient::PowerMode mode) | ||
541 | { | ||
542 | int32_t err = mDispatch.setPowerMode(mDevice, display, | ||
543 | static_cast<int32_t>(mode)); | ||
544 | return static_cast<Error>(err); | ||
545 | } | ||
546 | |||
547 | Error HwcHal::setVsyncEnabled(Display display, IComposerClient::Vsync enabled) | ||
548 | { | ||
549 | int32_t err = mDispatch.setVsyncEnabled(mDevice, display, | ||
550 | static_cast<int32_t>(enabled)); | ||
551 | return static_cast<Error>(err); | ||
552 | } | ||
553 | |||
554 | Error HwcHal::setColorTransform(Display display, const float* matrix, | ||
555 | int32_t hint) | ||
556 | { | ||
557 | int32_t err = mDispatch.setColorTransform(mDevice, display, matrix, hint); | ||
558 | return static_cast<Error>(err); | ||
559 | } | ||
560 | |||
561 | Error HwcHal::setClientTarget(Display display, buffer_handle_t target, | ||
562 | int32_t acquireFence, int32_t dataspace, | ||
563 | const std::vector<hwc_rect_t>& damage) | ||
564 | { | ||
565 | hwc_region region = { damage.size(), damage.data() }; | ||
566 | int32_t err = mDispatch.setClientTarget(mDevice, display, target, | ||
567 | acquireFence, dataspace, region); | ||
568 | return static_cast<Error>(err); | ||
569 | } | ||
570 | |||
571 | Error HwcHal::setOutputBuffer(Display display, buffer_handle_t buffer, | ||
572 | int32_t releaseFence) | ||
573 | { | ||
574 | int32_t err = mDispatch.setOutputBuffer(mDevice, display, buffer, | ||
575 | releaseFence); | ||
576 | // unlike in setClientTarget, releaseFence is owned by us | ||
577 | if (err == HWC2_ERROR_NONE && releaseFence >= 0) { | ||
578 | close(releaseFence); | ||
579 | } | ||
580 | |||
581 | return static_cast<Error>(err); | ||
582 | } | ||
583 | |||
584 | Error HwcHal::validateDisplay(Display display, | ||
585 | std::vector<Layer>* outChangedLayers, | ||
586 | std::vector<IComposerClient::Composition>* outCompositionTypes, | ||
587 | uint32_t* outDisplayRequestMask, | ||
588 | std::vector<Layer>* outRequestedLayers, | ||
589 | std::vector<uint32_t>* outRequestMasks) | ||
590 | { | ||
591 | uint32_t types_count = 0; | ||
592 | uint32_t reqs_count = 0; | ||
593 | int32_t err = mDispatch.validateDisplay(mDevice, display, | ||
594 | &types_count, &reqs_count); | ||
595 | mMustValidateDisplay = false; | ||
596 | |||
597 | if (err != HWC2_ERROR_NONE && err != HWC2_ERROR_HAS_CHANGES) { | ||
598 | return static_cast<Error>(err); | ||
599 | } | ||
600 | |||
601 | err = mDispatch.getChangedCompositionTypes(mDevice, display, | ||
602 | &types_count, nullptr, nullptr); | ||
603 | if (err != HWC2_ERROR_NONE) { | ||
604 | return static_cast<Error>(err); | ||
605 | } | ||
606 | |||
607 | outChangedLayers->resize(types_count); | ||
608 | outCompositionTypes->resize(types_count); | ||
609 | err = mDispatch.getChangedCompositionTypes(mDevice, display, | ||
610 | &types_count, outChangedLayers->data(), | ||
611 | reinterpret_cast< | ||
612 | std::underlying_type<IComposerClient::Composition>::type*>( | ||
613 | outCompositionTypes->data())); | ||
614 | if (err != HWC2_ERROR_NONE) { | ||
615 | outChangedLayers->clear(); | ||
616 | outCompositionTypes->clear(); | ||
617 | return static_cast<Error>(err); | ||
618 | } | ||
619 | |||
620 | int32_t display_reqs = 0; | ||
621 | err = mDispatch.getDisplayRequests(mDevice, display, &display_reqs, | ||
622 | &reqs_count, nullptr, nullptr); | ||
623 | if (err != HWC2_ERROR_NONE) { | ||
624 | outChangedLayers->clear(); | ||
625 | outCompositionTypes->clear(); | ||
626 | return static_cast<Error>(err); | ||
627 | } | ||
628 | |||
629 | outRequestedLayers->resize(reqs_count); | ||
630 | outRequestMasks->resize(reqs_count); | ||
631 | err = mDispatch.getDisplayRequests(mDevice, display, &display_reqs, | ||
632 | &reqs_count, outRequestedLayers->data(), | ||
633 | reinterpret_cast<int32_t*>(outRequestMasks->data())); | ||
634 | if (err != HWC2_ERROR_NONE) { | ||
635 | outChangedLayers->clear(); | ||
636 | outCompositionTypes->clear(); | ||
637 | |||
638 | outRequestedLayers->clear(); | ||
639 | outRequestMasks->clear(); | ||
640 | return static_cast<Error>(err); | ||
641 | } | ||
642 | |||
643 | *outDisplayRequestMask = display_reqs; | ||
644 | |||
645 | return static_cast<Error>(err); | ||
646 | } | ||
647 | |||
648 | Error HwcHal::acceptDisplayChanges(Display display) | ||
649 | { | ||
650 | int32_t err = mDispatch.acceptDisplayChanges(mDevice, display); | ||
651 | return static_cast<Error>(err); | ||
652 | } | ||
653 | |||
654 | Error HwcHal::presentDisplay(Display display, int32_t* outPresentFence, | ||
655 | std::vector<Layer>* outLayers, std::vector<int32_t>* outReleaseFences) | ||
656 | { | ||
657 | if (mMustValidateDisplay) { | ||
658 | return Error::NOT_VALIDATED; | ||
659 | } | ||
660 | |||
661 | *outPresentFence = -1; | ||
662 | int32_t err = mDispatch.presentDisplay(mDevice, display, outPresentFence); | ||
663 | if (err != HWC2_ERROR_NONE) { | ||
664 | return static_cast<Error>(err); | ||
665 | } | ||
666 | |||
667 | uint32_t count = 0; | ||
668 | err = mDispatch.getReleaseFences(mDevice, display, &count, | ||
669 | nullptr, nullptr); | ||
670 | if (err != HWC2_ERROR_NONE) { | ||
671 | ALOGW("failed to get release fences"); | ||
672 | return Error::NONE; | ||
673 | } | ||
674 | |||
675 | outLayers->resize(count); | ||
676 | outReleaseFences->resize(count); | ||
677 | err = mDispatch.getReleaseFences(mDevice, display, &count, | ||
678 | outLayers->data(), outReleaseFences->data()); | ||
679 | if (err != HWC2_ERROR_NONE) { | ||
680 | ALOGW("failed to get release fences"); | ||
681 | outLayers->clear(); | ||
682 | outReleaseFences->clear(); | ||
683 | return Error::NONE; | ||
684 | } | ||
685 | |||
686 | return static_cast<Error>(err); | ||
687 | } | ||
688 | |||
689 | Error HwcHal::setLayerCursorPosition(Display display, Layer layer, | ||
690 | int32_t x, int32_t y) | ||
691 | { | ||
692 | int32_t err = mDispatch.setCursorPosition(mDevice, display, layer, x, y); | ||
693 | return static_cast<Error>(err); | ||
694 | } | ||
695 | |||
696 | Error HwcHal::setLayerBuffer(Display display, Layer layer, | ||
697 | buffer_handle_t buffer, int32_t acquireFence) | ||
698 | { | ||
699 | int32_t err = mDispatch.setLayerBuffer(mDevice, display, layer, | ||
700 | buffer, acquireFence); | ||
701 | return static_cast<Error>(err); | ||
702 | } | ||
703 | |||
704 | Error HwcHal::setLayerSurfaceDamage(Display display, Layer layer, | ||
705 | const std::vector<hwc_rect_t>& damage) | ||
706 | { | ||
707 | hwc_region region = { damage.size(), damage.data() }; | ||
708 | int32_t err = mDispatch.setLayerSurfaceDamage(mDevice, display, layer, | ||
709 | region); | ||
710 | return static_cast<Error>(err); | ||
711 | } | ||
712 | |||
713 | Error HwcHal::setLayerBlendMode(Display display, Layer layer, int32_t mode) | ||
714 | { | ||
715 | int32_t err = mDispatch.setLayerBlendMode(mDevice, display, layer, mode); | ||
716 | return static_cast<Error>(err); | ||
717 | } | ||
718 | |||
719 | Error HwcHal::setLayerColor(Display display, Layer layer, | ||
720 | IComposerClient::Color color) | ||
721 | { | ||
722 | hwc_color_t hwc_color{color.r, color.g, color.b, color.a}; | ||
723 | int32_t err = mDispatch.setLayerColor(mDevice, display, layer, hwc_color); | ||
724 | return static_cast<Error>(err); | ||
725 | } | ||
726 | |||
727 | Error HwcHal::setLayerCompositionType(Display display, Layer layer, | ||
728 | int32_t type) | ||
729 | { | ||
730 | int32_t err = mDispatch.setLayerCompositionType(mDevice, display, layer, | ||
731 | type); | ||
732 | return static_cast<Error>(err); | ||
733 | } | ||
734 | |||
735 | Error HwcHal::setLayerDataspace(Display display, Layer layer, | ||
736 | int32_t dataspace) | ||
737 | { | ||
738 | int32_t err = mDispatch.setLayerDataspace(mDevice, display, layer, | ||
739 | dataspace); | ||
740 | return static_cast<Error>(err); | ||
741 | } | ||
742 | |||
743 | Error HwcHal::setLayerDisplayFrame(Display display, Layer layer, | ||
744 | const hwc_rect_t& frame) | ||
745 | { | ||
746 | int32_t err = mDispatch.setLayerDisplayFrame(mDevice, display, layer, | ||
747 | frame); | ||
748 | return static_cast<Error>(err); | ||
749 | } | ||
750 | |||
751 | Error HwcHal::setLayerPlaneAlpha(Display display, Layer layer, float alpha) | ||
752 | { | ||
753 | int32_t err = mDispatch.setLayerPlaneAlpha(mDevice, display, layer, | ||
754 | alpha); | ||
755 | return static_cast<Error>(err); | ||
756 | } | ||
757 | |||
758 | Error HwcHal::setLayerSidebandStream(Display display, Layer layer, | ||
759 | buffer_handle_t stream) | ||
760 | { | ||
761 | int32_t err = mDispatch.setLayerSidebandStream(mDevice, display, layer, | ||
762 | stream); | ||
763 | return static_cast<Error>(err); | ||
764 | } | ||
765 | |||
766 | Error HwcHal::setLayerSourceCrop(Display display, Layer layer, | ||
767 | const hwc_frect_t& crop) | ||
768 | { | ||
769 | int32_t err = mDispatch.setLayerSourceCrop(mDevice, display, layer, crop); | ||
770 | return static_cast<Error>(err); | ||
771 | } | ||
772 | |||
773 | Error HwcHal::setLayerTransform(Display display, Layer layer, | ||
774 | int32_t transform) | ||
775 | { | ||
776 | int32_t err = mDispatch.setLayerTransform(mDevice, display, layer, | ||
777 | transform); | ||
778 | return static_cast<Error>(err); | ||
779 | } | ||
780 | |||
781 | Error HwcHal::setLayerVisibleRegion(Display display, Layer layer, | ||
782 | const std::vector<hwc_rect_t>& visible) | ||
783 | { | ||
784 | hwc_region_t region = { visible.size(), visible.data() }; | ||
785 | int32_t err = mDispatch.setLayerVisibleRegion(mDevice, display, layer, | ||
786 | region); | ||
787 | return static_cast<Error>(err); | ||
788 | } | ||
789 | |||
790 | Error HwcHal::setLayerZOrder(Display display, Layer layer, uint32_t z) | ||
791 | { | ||
792 | int32_t err = mDispatch.setLayerZOrder(mDevice, display, layer, z); | ||
793 | return static_cast<Error>(err); | ||
794 | } | ||
795 | |||
796 | IComposer* HIDL_FETCH_IComposer(const char*) | ||
797 | { | ||
798 | const hw_module_t* module = nullptr; | ||
799 | int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &module); | ||
800 | if (err) { | ||
801 | ALOGI("falling back to FB HAL"); | ||
802 | err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); | ||
803 | } | ||
804 | if (err) { | ||
805 | ALOGE("failed to get hwcomposer or fb module"); | ||
806 | return nullptr; | ||
807 | } | ||
808 | |||
809 | return new HwcHal(module); | ||
810 | } | ||
811 | |||
812 | } // namespace implementation | ||
813 | } // namespace V2_1 | ||
814 | } // namespace composer | ||
815 | } // namespace graphics | ||
816 | } // namespace hardware | ||
817 | } // namespace android | ||
diff --git a/graphics/composer/2.1/default/Hwc.h b/graphics/composer/2.1/default/Hwc.h deleted file mode 100644 index e3f5ce68..00000000 --- a/graphics/composer/2.1/default/Hwc.h +++ /dev/null | |||
@@ -1,242 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H | ||
18 | #define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H | ||
19 | |||
20 | #include <atomic> | ||
21 | #include <condition_variable> | ||
22 | #include <memory> | ||
23 | #include <mutex> | ||
24 | #include <unordered_set> | ||
25 | #include <vector> | ||
26 | |||
27 | #include <android/hardware/graphics/composer/2.1/IComposer.h> | ||
28 | #define HWC2_INCLUDE_STRINGIFICATION | ||
29 | #define HWC2_USE_CPP11 | ||
30 | #include <hardware/hwcomposer2.h> | ||
31 | #undef HWC2_INCLUDE_STRINGIFICATION | ||
32 | #undef HWC2_USE_CPP11 | ||
33 | #include "ComposerBase.h" | ||
34 | |||
35 | namespace android { | ||
36 | class HWC2On1Adapter; | ||
37 | class HWC2OnFbAdapter; | ||
38 | } | ||
39 | |||
40 | namespace android { | ||
41 | namespace hardware { | ||
42 | namespace graphics { | ||
43 | namespace composer { | ||
44 | namespace V2_1 { | ||
45 | namespace implementation { | ||
46 | |||
47 | using android::hardware::graphics::common::V1_0::PixelFormat; | ||
48 | using android::hardware::graphics::common::V1_0::Transform; | ||
49 | using android::hardware::graphics::common::V1_0::Dataspace; | ||
50 | using android::hardware::graphics::common::V1_0::ColorMode; | ||
51 | using android::hardware::graphics::common::V1_0::ColorTransform; | ||
52 | using android::hardware::graphics::common::V1_0::Hdr; | ||
53 | |||
54 | class ComposerClient; | ||
55 | |||
56 | class HwcHal : public IComposer, public ComposerBase { | ||
57 | public: | ||
58 | HwcHal(const hw_module_t* module); | ||
59 | virtual ~HwcHal(); | ||
60 | |||
61 | // IComposer interface | ||
62 | Return<void> getCapabilities(getCapabilities_cb hidl_cb) override; | ||
63 | Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override; | ||
64 | Return<void> createClient(createClient_cb hidl_cb) override; | ||
65 | |||
66 | // ComposerBase interface | ||
67 | bool hasCapability(hwc2_capability_t capability) override; | ||
68 | void removeClient() override; | ||
69 | void enableCallback(bool enable) override; | ||
70 | uint32_t getMaxVirtualDisplayCount() override; | ||
71 | Error createVirtualDisplay(uint32_t width, uint32_t height, | ||
72 | PixelFormat* format, Display* outDisplay) override; | ||
73 | Error destroyVirtualDisplay(Display display) override; | ||
74 | |||
75 | Error createLayer(Display display, Layer* outLayer) override; | ||
76 | Error destroyLayer(Display display, Layer layer) override; | ||
77 | |||
78 | Error getActiveConfig(Display display, Config* outConfig) override; | ||
79 | Error getClientTargetSupport(Display display, | ||
80 | uint32_t width, uint32_t height, | ||
81 | PixelFormat format, Dataspace dataspace) override; | ||
82 | Error getColorModes(Display display, | ||
83 | hidl_vec<ColorMode>* outModes) override; | ||
84 | Error getDisplayAttribute(Display display, Config config, | ||
85 | IComposerClient::Attribute attribute, int32_t* outValue) override; | ||
86 | Error getDisplayConfigs(Display display, | ||
87 | hidl_vec<Config>* outConfigs) override; | ||
88 | Error getDisplayName(Display display, hidl_string* outName) override; | ||
89 | Error getDisplayType(Display display, | ||
90 | IComposerClient::DisplayType* outType) override; | ||
91 | Error getDozeSupport(Display display, bool* outSupport) override; | ||
92 | Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes, | ||
93 | float* outMaxLuminance, float* outMaxAverageLuminance, | ||
94 | float* outMinLuminance) override; | ||
95 | |||
96 | Error setActiveConfig(Display display, Config config) override; | ||
97 | Error setColorMode(Display display, ColorMode mode) override; | ||
98 | Error setPowerMode(Display display, | ||
99 | IComposerClient::PowerMode mode) override; | ||
100 | Error setVsyncEnabled(Display display, | ||
101 | IComposerClient::Vsync enabled) override; | ||
102 | |||
103 | Error setColorTransform(Display display, const float* matrix, | ||
104 | int32_t hint) override; | ||
105 | Error setClientTarget(Display display, buffer_handle_t target, | ||
106 | int32_t acquireFence, int32_t dataspace, | ||
107 | const std::vector<hwc_rect_t>& damage) override; | ||
108 | Error setOutputBuffer(Display display, buffer_handle_t buffer, | ||
109 | int32_t releaseFence) override; | ||
110 | Error validateDisplay(Display display, | ||
111 | std::vector<Layer>* outChangedLayers, | ||
112 | std::vector<IComposerClient::Composition>* outCompositionTypes, | ||
113 | uint32_t* outDisplayRequestMask, | ||
114 | std::vector<Layer>* outRequestedLayers, | ||
115 | std::vector<uint32_t>* outRequestMasks) override; | ||
116 | Error acceptDisplayChanges(Display display) override; | ||
117 | Error presentDisplay(Display display, int32_t* outPresentFence, | ||
118 | std::vector<Layer>* outLayers, | ||
119 | std::vector<int32_t>* outReleaseFences) override; | ||
120 | |||
121 | Error setLayerCursorPosition(Display display, Layer layer, | ||
122 | int32_t x, int32_t y) override; | ||
123 | Error setLayerBuffer(Display display, Layer layer, | ||
124 | buffer_handle_t buffer, int32_t acquireFence) override; | ||
125 | Error setLayerSurfaceDamage(Display display, Layer layer, | ||
126 | const std::vector<hwc_rect_t>& damage) override; | ||
127 | Error setLayerBlendMode(Display display, Layer layer, | ||
128 | int32_t mode) override; | ||
129 | Error setLayerColor(Display display, Layer layer, | ||
130 | IComposerClient::Color color) override; | ||
131 | Error setLayerCompositionType(Display display, Layer layer, | ||
132 | int32_t type) override; | ||
133 | Error setLayerDataspace(Display display, Layer layer, | ||
134 | int32_t dataspace) override; | ||
135 | Error setLayerDisplayFrame(Display display, Layer layer, | ||
136 | const hwc_rect_t& frame) override; | ||
137 | Error setLayerPlaneAlpha(Display display, Layer layer, | ||
138 | float alpha) override; | ||
139 | Error setLayerSidebandStream(Display display, Layer layer, | ||
140 | buffer_handle_t stream) override; | ||
141 | Error setLayerSourceCrop(Display display, Layer layer, | ||
142 | const hwc_frect_t& crop) override; | ||
143 | Error setLayerTransform(Display display, Layer layer, | ||
144 | int32_t transform) override; | ||
145 | Error setLayerVisibleRegion(Display display, Layer layer, | ||
146 | const std::vector<hwc_rect_t>& visible) override; | ||
147 | Error setLayerZOrder(Display display, Layer layer, uint32_t z) override; | ||
148 | |||
149 | private: | ||
150 | uint32_t initWithHwc(const hw_module_t* module); | ||
151 | uint32_t initWithFb(const hw_module_t* module); | ||
152 | |||
153 | void initCapabilities(); | ||
154 | |||
155 | template<typename T> | ||
156 | void initDispatch(hwc2_function_descriptor_t desc, T* outPfn); | ||
157 | void initDispatch(); | ||
158 | |||
159 | sp<ComposerClient> getClient(); | ||
160 | |||
161 | static void hotplugHook(hwc2_callback_data_t callbackData, | ||
162 | hwc2_display_t display, int32_t connected); | ||
163 | static void refreshHook(hwc2_callback_data_t callbackData, | ||
164 | hwc2_display_t display); | ||
165 | static void vsyncHook(hwc2_callback_data_t callbackData, | ||
166 | hwc2_display_t display, int64_t timestamp); | ||
167 | |||
168 | hwc2_device_t* mDevice; | ||
169 | |||
170 | std::unordered_set<hwc2_capability_t> mCapabilities; | ||
171 | |||
172 | struct { | ||
173 | HWC2_PFN_ACCEPT_DISPLAY_CHANGES acceptDisplayChanges; | ||
174 | HWC2_PFN_CREATE_LAYER createLayer; | ||
175 | HWC2_PFN_CREATE_VIRTUAL_DISPLAY createVirtualDisplay; | ||
176 | HWC2_PFN_DESTROY_LAYER destroyLayer; | ||
177 | HWC2_PFN_DESTROY_VIRTUAL_DISPLAY destroyVirtualDisplay; | ||
178 | HWC2_PFN_DUMP dump; | ||
179 | HWC2_PFN_GET_ACTIVE_CONFIG getActiveConfig; | ||
180 | HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES getChangedCompositionTypes; | ||
181 | HWC2_PFN_GET_CLIENT_TARGET_SUPPORT getClientTargetSupport; | ||
182 | HWC2_PFN_GET_COLOR_MODES getColorModes; | ||
183 | HWC2_PFN_GET_DISPLAY_ATTRIBUTE getDisplayAttribute; | ||
184 | HWC2_PFN_GET_DISPLAY_CONFIGS getDisplayConfigs; | ||
185 | HWC2_PFN_GET_DISPLAY_NAME getDisplayName; | ||
186 | HWC2_PFN_GET_DISPLAY_REQUESTS getDisplayRequests; | ||
187 | HWC2_PFN_GET_DISPLAY_TYPE getDisplayType; | ||
188 | HWC2_PFN_GET_DOZE_SUPPORT getDozeSupport; | ||
189 | HWC2_PFN_GET_HDR_CAPABILITIES getHdrCapabilities; | ||
190 | HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT getMaxVirtualDisplayCount; | ||
191 | HWC2_PFN_GET_RELEASE_FENCES getReleaseFences; | ||
192 | HWC2_PFN_PRESENT_DISPLAY presentDisplay; | ||
193 | HWC2_PFN_REGISTER_CALLBACK registerCallback; | ||
194 | HWC2_PFN_SET_ACTIVE_CONFIG setActiveConfig; | ||
195 | HWC2_PFN_SET_CLIENT_TARGET setClientTarget; | ||
196 | HWC2_PFN_SET_COLOR_MODE setColorMode; | ||
197 | HWC2_PFN_SET_COLOR_TRANSFORM setColorTransform; | ||
198 | HWC2_PFN_SET_CURSOR_POSITION setCursorPosition; | ||
199 | HWC2_PFN_SET_LAYER_BLEND_MODE setLayerBlendMode; | ||
200 | HWC2_PFN_SET_LAYER_BUFFER setLayerBuffer; | ||
201 | HWC2_PFN_SET_LAYER_COLOR setLayerColor; | ||
202 | HWC2_PFN_SET_LAYER_COMPOSITION_TYPE setLayerCompositionType; | ||
203 | HWC2_PFN_SET_LAYER_DATASPACE setLayerDataspace; | ||
204 | HWC2_PFN_SET_LAYER_DISPLAY_FRAME setLayerDisplayFrame; | ||
205 | HWC2_PFN_SET_LAYER_PLANE_ALPHA setLayerPlaneAlpha; | ||
206 | HWC2_PFN_SET_LAYER_SIDEBAND_STREAM setLayerSidebandStream; | ||
207 | HWC2_PFN_SET_LAYER_SOURCE_CROP setLayerSourceCrop; | ||
208 | HWC2_PFN_SET_LAYER_SURFACE_DAMAGE setLayerSurfaceDamage; | ||
209 | HWC2_PFN_SET_LAYER_TRANSFORM setLayerTransform; | ||
210 | HWC2_PFN_SET_LAYER_VISIBLE_REGION setLayerVisibleRegion; | ||
211 | HWC2_PFN_SET_LAYER_Z_ORDER setLayerZOrder; | ||
212 | HWC2_PFN_SET_OUTPUT_BUFFER setOutputBuffer; | ||
213 | HWC2_PFN_SET_POWER_MODE setPowerMode; | ||
214 | HWC2_PFN_SET_VSYNC_ENABLED setVsyncEnabled; | ||
215 | HWC2_PFN_VALIDATE_DISPLAY validateDisplay; | ||
216 | } mDispatch; | ||
217 | |||
218 | std::mutex mClientMutex; | ||
219 | std::condition_variable mClientDestroyedWait; | ||
220 | wp<ComposerClient> mClient; | ||
221 | |||
222 | std::atomic<bool> mMustValidateDisplay; | ||
223 | |||
224 | // If the HWC implementation version is < 2.0, use an adapter to interface | ||
225 | // between HWC 2.0 <-> HWC 1.X. | ||
226 | std::unique_ptr<HWC2On1Adapter> mAdapter; | ||
227 | |||
228 | // If there is no HWC implementation, use an adapter to interface between | ||
229 | // HWC 2.0 <-> FB HAL. | ||
230 | std::unique_ptr<HWC2OnFbAdapter> mFbAdapter; | ||
231 | }; | ||
232 | |||
233 | extern "C" IComposer* HIDL_FETCH_IComposer(const char* name); | ||
234 | |||
235 | } // namespace implementation | ||
236 | } // namespace V2_1 | ||
237 | } // namespace composer | ||
238 | } // namespace graphics | ||
239 | } // namespace hardware | ||
240 | } // namespace android | ||
241 | |||
242 | #endif // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H | ||
diff --git a/graphics/composer/2.1/default/passthrough.cpp b/graphics/composer/2.1/default/passthrough.cpp new file mode 100644 index 00000000..ef7ed7c8 --- /dev/null +++ b/graphics/composer/2.1/default/passthrough.cpp | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * Copyright 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include <android/hardware/graphics/composer/2.1/IComposer.h> | ||
18 | #include <composer-passthrough/2.1/HwcLoader.h> | ||
19 | |||
20 | using android::hardware::graphics::composer::V2_1::IComposer; | ||
21 | using android::hardware::graphics::composer::V2_1::passthrough::HwcLoader; | ||
22 | |||
23 | extern "C" IComposer* HIDL_FETCH_IComposer(const char* /* name */) { | ||
24 | return HwcLoader::load(); | ||
25 | } | ||
diff --git a/graphics/composer/2.1/utils/command-buffer/Android.bp b/graphics/composer/2.1/utils/command-buffer/Android.bp index e8d41c2b..140d9bb6 100644 --- a/graphics/composer/2.1/utils/command-buffer/Android.bp +++ b/graphics/composer/2.1/utils/command-buffer/Android.bp | |||
@@ -2,6 +2,15 @@ cc_library_headers { | |||
2 | name: "android.hardware.graphics.composer@2.1-command-buffer", | 2 | name: "android.hardware.graphics.composer@2.1-command-buffer", |
3 | defaults: ["hidl_defaults"], | 3 | defaults: ["hidl_defaults"], |
4 | vendor_available: true, | 4 | vendor_available: true, |
5 | shared_libs: ["android.hardware.graphics.composer@2.1"], | 5 | shared_libs: [ |
6 | "android.hardware.graphics.composer@2.1", | ||
7 | "libfmq", | ||
8 | "libsync", | ||
9 | ], | ||
10 | export_shared_lib_headers: [ | ||
11 | "android.hardware.graphics.composer@2.1", | ||
12 | "libfmq", | ||
13 | "libsync", | ||
14 | ], | ||
6 | export_include_dirs: ["include"], | 15 | export_include_dirs: ["include"], |
7 | } | 16 | } |
diff --git a/graphics/composer/2.1/utils/hal/Android.bp b/graphics/composer/2.1/utils/hal/Android.bp new file mode 100644 index 00000000..f24e7682 --- /dev/null +++ b/graphics/composer/2.1/utils/hal/Android.bp | |||
@@ -0,0 +1,37 @@ | |||
1 | // | ||
2 | // Copyright (C) 2018 The Android Open Source Project | ||
3 | // | ||
4 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | // you may not use this file except in compliance with the License. | ||
6 | // You may obtain a copy of the License at | ||
7 | // | ||
8 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | // | ||
10 | // Unless required by applicable law or agreed to in writing, software | ||
11 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | // See the License for the specific language governing permissions and | ||
14 | // limitations under the License. | ||
15 | |||
16 | cc_library_headers { | ||
17 | name: "android.hardware.graphics.composer@2.1-hal", | ||
18 | defaults: ["hidl_defaults"], | ||
19 | vendor_available: true, | ||
20 | shared_libs: [ | ||
21 | "android.hardware.graphics.composer@2.1", | ||
22 | "android.hardware.graphics.mapper@2.0", | ||
23 | "libhardware", // TODO remove hwcomposer2.h dependency | ||
24 | ], | ||
25 | export_shared_lib_headers: [ | ||
26 | "android.hardware.graphics.composer@2.1", | ||
27 | "android.hardware.graphics.mapper@2.0", | ||
28 | "libhardware", | ||
29 | ], | ||
30 | header_libs: [ | ||
31 | "android.hardware.graphics.composer@2.1-command-buffer", | ||
32 | ], | ||
33 | export_header_lib_headers: [ | ||
34 | "android.hardware.graphics.composer@2.1-command-buffer", | ||
35 | ], | ||
36 | export_include_dirs: ["include"], | ||
37 | } | ||
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h new file mode 100644 index 00000000..581dc962 --- /dev/null +++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h | |||
@@ -0,0 +1,157 @@ | |||
1 | /* | ||
2 | * Copyright 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #pragma once | ||
18 | |||
19 | #ifndef LOG_TAG | ||
20 | #warning "Composer.h included without LOG_TAG" | ||
21 | #endif | ||
22 | |||
23 | #include <array> | ||
24 | #include <chrono> | ||
25 | #include <condition_variable> | ||
26 | #include <memory> | ||
27 | #include <mutex> | ||
28 | #include <vector> | ||
29 | |||
30 | #include <android/hardware/graphics/composer/2.1/IComposer.h> | ||
31 | #include <android/hardware/graphics/composer/2.1/IComposerClient.h> | ||
32 | #include <composer-hal/2.1/ComposerClient.h> | ||
33 | #include <composer-hal/2.1/ComposerHal.h> | ||
34 | |||
35 | namespace android { | ||
36 | namespace hardware { | ||
37 | namespace graphics { | ||
38 | namespace composer { | ||
39 | namespace V2_1 { | ||
40 | namespace hal { | ||
41 | |||
42 | namespace detail { | ||
43 | |||
44 | // ComposerImpl implements V2_*::IComposer on top of V2_*::ComposerHal | ||
45 | template <typename Interface, typename Hal> | ||
46 | class ComposerImpl : public Interface { | ||
47 | public: | ||
48 | static std::unique_ptr<ComposerImpl> create(std::unique_ptr<Hal> hal) { | ||
49 | return std::make_unique<ComposerImpl>(std::move(hal)); | ||
50 | } | ||
51 | |||
52 | ComposerImpl(std::unique_ptr<Hal> hal) : mHal(std::move(hal)) {} | ||
53 | |||
54 | // IComposer 2.1 interface | ||
55 | |||
56 | Return<void> getCapabilities(IComposer::getCapabilities_cb hidl_cb) override { | ||
57 | const std::array<IComposer::Capability, 3> all_caps = {{ | ||
58 | IComposer::Capability::SIDEBAND_STREAM, | ||
59 | IComposer::Capability::SKIP_CLIENT_COLOR_TRANSFORM, | ||
60 | IComposer::Capability::PRESENT_FENCE_IS_NOT_RELIABLE, | ||
61 | }}; | ||
62 | |||
63 | std::vector<IComposer::Capability> caps; | ||
64 | for (auto cap : all_caps) { | ||
65 | if (mHal->hasCapability(static_cast<hwc2_capability_t>(cap))) { | ||
66 | caps.push_back(cap); | ||
67 | } | ||
68 | } | ||
69 | |||
70 | hidl_vec<IComposer::Capability> caps_reply; | ||
71 | caps_reply.setToExternal(caps.data(), caps.size()); | ||
72 | hidl_cb(caps_reply); | ||
73 | return Void(); | ||
74 | } | ||
75 | |||
76 | Return<void> dumpDebugInfo(IComposer::dumpDebugInfo_cb hidl_cb) override { | ||
77 | hidl_cb(mHal->dumpDebugInfo()); | ||
78 | return Void(); | ||
79 | } | ||
80 | |||
81 | Return<void> createClient(IComposer::createClient_cb hidl_cb) override { | ||
82 | std::unique_lock<std::mutex> lock(mClientMutex); | ||
83 | if (!waitForClientDestroyedLocked(lock)) { | ||
84 | hidl_cb(Error::NO_RESOURCES, nullptr); | ||
85 | return Void(); | ||
86 | } | ||
87 | |||
88 | sp<IComposerClient> client = createClient(); | ||
89 | if (!client) { | ||
90 | hidl_cb(Error::NO_RESOURCES, nullptr); | ||
91 | return Void(); | ||
92 | } | ||
93 | |||
94 | mClient = client; | ||
95 | hidl_cb(Error::NONE, client); | ||
96 | return Void(); | ||
97 | } | ||
98 | |||
99 | protected: | ||
100 | bool waitForClientDestroyedLocked(std::unique_lock<std::mutex>& lock) { | ||
101 | if (mClient != nullptr) { | ||
102 | using namespace std::chrono_literals; | ||
103 | |||
104 | // In surface flinger we delete a composer client on one thread and | ||
105 | // then create a new client on another thread. Although surface | ||
106 | // flinger ensures the calls are made in that sequence (destroy and | ||
107 | // then create), sometimes the calls land in the composer service | ||
108 | // inverted (create and then destroy). Wait for a brief period to | ||
109 | // see if the existing client is destroyed. | ||
110 | ALOGD("waiting for previous client to be destroyed"); | ||
111 | mClientDestroyedCondition.wait_for( | ||
112 | lock, 1s, [this]() -> bool { return mClient.promote() == nullptr; }); | ||
113 | if (mClient.promote() != nullptr) { | ||
114 | ALOGD("previous client was not destroyed"); | ||
115 | } else { | ||
116 | mClient.clear(); | ||
117 | } | ||
118 | } | ||
119 | |||
120 | return mClient == nullptr; | ||
121 | } | ||
122 | |||
123 | void onClientDestroyed() { | ||
124 | std::lock_guard<std::mutex> lock(mClientMutex); | ||
125 | mClient.clear(); | ||
126 | mClientDestroyedCondition.notify_all(); | ||
127 | } | ||
128 | |||
129 | virtual IComposerClient* createClient() { | ||
130 | auto client = ComposerClient::create(mHal.get()); | ||
131 | if (!client) { | ||
132 | return nullptr; | ||
133 | } | ||
134 | |||
135 | auto clientDestroyed = [this]() { onClientDestroyed(); }; | ||
136 | client->setOnClientDestroyed(clientDestroyed); | ||
137 | |||
138 | return client.release(); | ||
139 | } | ||
140 | |||
141 | const std::unique_ptr<Hal> mHal; | ||
142 | |||
143 | std::mutex mClientMutex; | ||
144 | wp<IComposerClient> mClient; | ||
145 | std::condition_variable mClientDestroyedCondition; | ||
146 | }; | ||
147 | |||
148 | } // namespace detail | ||
149 | |||
150 | using Composer = detail::ComposerImpl<IComposer, ComposerHal>; | ||
151 | |||
152 | } // namespace hal | ||
153 | } // namespace V2_1 | ||
154 | } // namespace composer | ||
155 | } // namespace graphics | ||
156 | } // namespace hardware | ||
157 | } // namespace android | ||
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h new file mode 100644 index 00000000..86525b87 --- /dev/null +++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h | |||
@@ -0,0 +1,396 @@ | |||
1 | /* | ||
2 | * Copyright 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #pragma once | ||
18 | |||
19 | #ifndef LOG_TAG | ||
20 | #warning "ComposerClient.h included without LOG_TAG" | ||
21 | #endif | ||
22 | |||
23 | #include <memory> | ||
24 | #include <mutex> | ||
25 | #include <vector> | ||
26 | |||
27 | #include <android/hardware/graphics/composer/2.1/IComposerClient.h> | ||
28 | #include <composer-hal/2.1/ComposerCommandEngine.h> | ||
29 | #include <composer-hal/2.1/ComposerHal.h> | ||
30 | #include <composer-hal/2.1/ComposerResources.h> | ||
31 | #include <log/log.h> | ||
32 | |||
33 | namespace android { | ||
34 | namespace hardware { | ||
35 | namespace graphics { | ||
36 | namespace composer { | ||
37 | namespace V2_1 { | ||
38 | namespace hal { | ||
39 | |||
40 | namespace detail { | ||
41 | |||
42 | // ComposerClientImpl implements V2_*::IComposerClient on top of V2_*::ComposerHal | ||
43 | template <typename Interface, typename Hal> | ||
44 | class ComposerClientImpl : public Interface { | ||
45 | public: | ||
46 | static std::unique_ptr<ComposerClientImpl> create(Hal* hal) { | ||
47 | auto client = std::make_unique<ComposerClientImpl>(hal); | ||
48 | return client->init() ? std::move(client) : nullptr; | ||
49 | } | ||
50 | |||
51 | ComposerClientImpl(Hal* hal) : mHal(hal) {} | ||
52 | |||
53 | virtual ~ComposerClientImpl() { | ||
54 | // not initialized | ||
55 | if (!mCommandEngine) { | ||
56 | return; | ||
57 | } | ||
58 | |||
59 | ALOGD("destroying composer client"); | ||
60 | |||
61 | mHal->unregisterEventCallback(); | ||
62 | destroyResources(); | ||
63 | if (mOnClientDestroyed) { | ||
64 | mOnClientDestroyed(); | ||
65 | } | ||
66 | |||
67 | ALOGD("removed composer client"); | ||
68 | } | ||
69 | |||
70 | bool init() { | ||
71 | mResources = createResources(); | ||
72 | if (!mResources) { | ||
73 | ALOGE("failed to create composer resources"); | ||
74 | return false; | ||
75 | } | ||
76 | |||
77 | mCommandEngine = createCommandEngine(); | ||
78 | |||
79 | return true; | ||
80 | } | ||
81 | |||
82 | void setOnClientDestroyed(std::function<void()> onClientDestroyed) { | ||
83 | mOnClientDestroyed = onClientDestroyed; | ||
84 | } | ||
85 | |||
86 | // IComposerClient 2.1 interface | ||
87 | |||
88 | class HalEventCallback : public Hal::EventCallback { | ||
89 | public: | ||
90 | HalEventCallback(const sp<IComposerCallback> callback, ComposerResources* resources) | ||
91 | : mCallback(callback), mResources(resources) {} | ||
92 | |||
93 | void onHotplug(Display display, IComposerCallback::Connection connected) { | ||
94 | if (connected == IComposerCallback::Connection::CONNECTED) { | ||
95 | mResources->addPhysicalDisplay(display); | ||
96 | } else if (connected == IComposerCallback::Connection::DISCONNECTED) { | ||
97 | mResources->removeDisplay(display); | ||
98 | } | ||
99 | |||
100 | auto ret = mCallback->onHotplug(display, connected); | ||
101 | ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s", ret.description().c_str()); | ||
102 | } | ||
103 | |||
104 | void onRefresh(Display display) { | ||
105 | auto ret = mCallback->onRefresh(display); | ||
106 | ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s", ret.description().c_str()); | ||
107 | } | ||
108 | |||
109 | void onVsync(Display display, int64_t timestamp) { | ||
110 | auto ret = mCallback->onVsync(display, timestamp); | ||
111 | ALOGE_IF(!ret.isOk(), "failed to send onVsync: %s", ret.description().c_str()); | ||
112 | } | ||
113 | |||
114 | protected: | ||
115 | const sp<IComposerCallback> mCallback; | ||
116 | ComposerResources* const mResources; | ||
117 | }; | ||
118 | |||
119 | Return<void> registerCallback(const sp<IComposerCallback>& callback) override { | ||
120 | // no locking as we require this function to be called only once | ||
121 | mHalEventCallback = std::make_unique<HalEventCallback>(callback, mResources.get()); | ||
122 | mHal->registerEventCallback(mHalEventCallback.get()); | ||
123 | return Void(); | ||
124 | } | ||
125 | |||
126 | Return<uint32_t> getMaxVirtualDisplayCount() override { | ||
127 | return mHal->getMaxVirtualDisplayCount(); | ||
128 | } | ||
129 | |||
130 | Return<void> createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat formatHint, | ||
131 | uint32_t outputBufferSlotCount, | ||
132 | IComposerClient::createVirtualDisplay_cb hidl_cb) override { | ||
133 | Display display = 0; | ||
134 | Error err = mHal->createVirtualDisplay(width, height, &formatHint, &display); | ||
135 | if (err == Error::NONE) { | ||
136 | mResources->addVirtualDisplay(display, outputBufferSlotCount); | ||
137 | } | ||
138 | |||
139 | hidl_cb(err, display, formatHint); | ||
140 | return Void(); | ||
141 | } | ||
142 | |||
143 | Return<Error> destroyVirtualDisplay(Display display) override { | ||
144 | Error err = mHal->destroyVirtualDisplay(display); | ||
145 | if (err == Error::NONE) { | ||
146 | mResources->removeDisplay(display); | ||
147 | } | ||
148 | |||
149 | return err; | ||
150 | } | ||
151 | |||
152 | Return<void> createLayer(Display display, uint32_t bufferSlotCount, | ||
153 | IComposerClient::createLayer_cb hidl_cb) override { | ||
154 | Layer layer = 0; | ||
155 | Error err = mHal->createLayer(display, &layer); | ||
156 | if (err == Error::NONE) { | ||
157 | err = mResources->addLayer(display, layer, bufferSlotCount); | ||
158 | if (err != Error::NONE) { | ||
159 | // The display entry may have already been removed by onHotplug. | ||
160 | // Note: We do not destroy the layer on this error as the hotplug | ||
161 | // disconnect invalidates the display id. The implementation should | ||
162 | // ensure all layers for the display are destroyed. | ||
163 | layer = 0; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | hidl_cb(err, layer); | ||
168 | return Void(); | ||
169 | } | ||
170 | |||
171 | Return<Error> destroyLayer(Display display, Layer layer) override { | ||
172 | Error err = mHal->destroyLayer(display, layer); | ||
173 | if (err == Error::NONE) { | ||
174 | mResources->removeLayer(display, layer); | ||
175 | } | ||
176 | |||
177 | return err; | ||
178 | } | ||
179 | |||
180 | Return<void> getActiveConfig(Display display, | ||
181 | IComposerClient::getActiveConfig_cb hidl_cb) override { | ||
182 | Config config = 0; | ||
183 | Error err = mHal->getActiveConfig(display, &config); | ||
184 | hidl_cb(err, config); | ||
185 | return Void(); | ||
186 | } | ||
187 | |||
188 | Return<Error> getClientTargetSupport(Display display, uint32_t width, uint32_t height, | ||
189 | PixelFormat format, Dataspace dataspace) override { | ||
190 | Error err = mHal->getClientTargetSupport(display, width, height, format, dataspace); | ||
191 | return err; | ||
192 | } | ||
193 | |||
194 | Return<void> getColorModes(Display display, | ||
195 | IComposerClient::getColorModes_cb hidl_cb) override { | ||
196 | hidl_vec<ColorMode> modes; | ||
197 | Error err = mHal->getColorModes(display, &modes); | ||
198 | hidl_cb(err, modes); | ||
199 | return Void(); | ||
200 | } | ||
201 | |||
202 | Return<void> getDisplayAttribute(Display display, Config config, | ||
203 | IComposerClient::Attribute attribute, | ||
204 | IComposerClient::getDisplayAttribute_cb hidl_cb) override { | ||
205 | int32_t value = 0; | ||
206 | Error err = mHal->getDisplayAttribute(display, config, attribute, &value); | ||
207 | hidl_cb(err, value); | ||
208 | return Void(); | ||
209 | } | ||
210 | |||
211 | Return<void> getDisplayConfigs(Display display, | ||
212 | IComposerClient::getDisplayConfigs_cb hidl_cb) override { | ||
213 | hidl_vec<Config> configs; | ||
214 | Error err = mHal->getDisplayConfigs(display, &configs); | ||
215 | hidl_cb(err, configs); | ||
216 | return Void(); | ||
217 | } | ||
218 | |||
219 | Return<void> getDisplayName(Display display, | ||
220 | IComposerClient::getDisplayName_cb hidl_cb) override { | ||
221 | hidl_string name; | ||
222 | Error err = mHal->getDisplayName(display, &name); | ||
223 | hidl_cb(err, name); | ||
224 | return Void(); | ||
225 | } | ||
226 | |||
227 | Return<void> getDisplayType(Display display, | ||
228 | IComposerClient::getDisplayType_cb hidl_cb) override { | ||
229 | IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID; | ||
230 | Error err = mHal->getDisplayType(display, &type); | ||
231 | hidl_cb(err, type); | ||
232 | return Void(); | ||
233 | } | ||
234 | |||
235 | Return<void> getDozeSupport(Display display, | ||
236 | IComposerClient::getDozeSupport_cb hidl_cb) override { | ||
237 | bool support = false; | ||
238 | Error err = mHal->getDozeSupport(display, &support); | ||
239 | hidl_cb(err, support); | ||
240 | return Void(); | ||
241 | } | ||
242 | |||
243 | Return<void> getHdrCapabilities(Display display, | ||
244 | IComposerClient::getHdrCapabilities_cb hidl_cb) override { | ||
245 | hidl_vec<Hdr> types; | ||
246 | float max_lumi = 0.0f; | ||
247 | float max_avg_lumi = 0.0f; | ||
248 | float min_lumi = 0.0f; | ||
249 | Error err = mHal->getHdrCapabilities(display, &types, &max_lumi, &max_avg_lumi, &min_lumi); | ||
250 | hidl_cb(err, types, max_lumi, max_avg_lumi, min_lumi); | ||
251 | return Void(); | ||
252 | } | ||
253 | |||
254 | Return<Error> setActiveConfig(Display display, Config config) override { | ||
255 | Error err = mHal->setActiveConfig(display, config); | ||
256 | return err; | ||
257 | } | ||
258 | |||
259 | Return<Error> setColorMode(Display display, ColorMode mode) override { | ||
260 | Error err = mHal->setColorMode(display, mode); | ||
261 | return err; | ||
262 | } | ||
263 | |||
264 | Return<Error> setPowerMode(Display display, IComposerClient::PowerMode mode) override { | ||
265 | Error err = mHal->setPowerMode(display, mode); | ||
266 | return err; | ||
267 | } | ||
268 | |||
269 | Return<Error> setVsyncEnabled(Display display, IComposerClient::Vsync enabled) override { | ||
270 | Error err = mHal->setVsyncEnabled(display, enabled); | ||
271 | return err; | ||
272 | } | ||
273 | |||
274 | Return<Error> setClientTargetSlotCount(Display display, | ||
275 | uint32_t clientTargetSlotCount) override { | ||
276 | return mResources->setDisplayClientTargetCacheSize(display, clientTargetSlotCount); | ||
277 | } | ||
278 | |||
279 | Return<Error> setInputCommandQueue(const MQDescriptorSync<uint32_t>& descriptor) override { | ||
280 | std::lock_guard<std::mutex> lock(mCommandEngineMutex); | ||
281 | return mCommandEngine->setInputMQDescriptor(descriptor) ? Error::NONE : Error::NO_RESOURCES; | ||
282 | } | ||
283 | |||
284 | Return<void> getOutputCommandQueue(IComposerClient::getOutputCommandQueue_cb hidl_cb) override { | ||
285 | // no locking as we require this function to be called inside | ||
286 | // executeCommands_cb | ||
287 | auto outDescriptor = mCommandEngine->getOutputMQDescriptor(); | ||
288 | if (outDescriptor) { | ||
289 | hidl_cb(Error::NONE, *outDescriptor); | ||
290 | } else { | ||
291 | hidl_cb(Error::NO_RESOURCES, CommandQueueType::Descriptor()); | ||
292 | } | ||
293 | |||
294 | return Void(); | ||
295 | } | ||
296 | |||
297 | Return<void> executeCommands(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles, | ||
298 | IComposerClient::executeCommands_cb hidl_cb) override { | ||
299 | std::lock_guard<std::mutex> lock(mCommandEngineMutex); | ||
300 | bool outChanged = false; | ||
301 | uint32_t outLength = 0; | ||
302 | hidl_vec<hidl_handle> outHandles; | ||
303 | Error error = | ||
304 | mCommandEngine->execute(inLength, inHandles, &outChanged, &outLength, &outHandles); | ||
305 | |||
306 | hidl_cb(error, outChanged, outLength, outHandles); | ||
307 | |||
308 | mCommandEngine->reset(); | ||
309 | |||
310 | return Void(); | ||
311 | } | ||
312 | |||
313 | protected: | ||
314 | virtual std::unique_ptr<ComposerResources> createResources() { | ||
315 | return ComposerResources::create(); | ||
316 | } | ||
317 | |||
318 | virtual std::unique_ptr<ComposerCommandEngine> createCommandEngine() { | ||
319 | return std::make_unique<ComposerCommandEngine>(mHal, mResources.get()); | ||
320 | } | ||
321 | |||
322 | void destroyResources() { | ||
323 | // We want to call hwc2_close here (and move hwc2_open to the | ||
324 | // constructor), with the assumption that hwc2_close would | ||
325 | // | ||
326 | // - clean up all resources owned by the client | ||
327 | // - make sure all displays are blank (since there is no layer) | ||
328 | // | ||
329 | // But since SF used to crash at this point, different hwcomposer2 | ||
330 | // implementations behave differently on hwc2_close. Our only portable | ||
331 | // choice really is to abort(). But that is not an option anymore | ||
332 | // because we might also have VTS or VR as clients that can come and go. | ||
333 | // | ||
334 | // Below we manually clean all resources (layers and virtual | ||
335 | // displays), and perform a presentDisplay afterwards. | ||
336 | mResources->clear([this](Display display, bool isVirtual, const std::vector<Layer> layers) { | ||
337 | ALOGW("destroying client resources for display %" PRIu64, display); | ||
338 | |||
339 | for (auto layer : layers) { | ||
340 | mHal->destroyLayer(display, layer); | ||
341 | } | ||
342 | |||
343 | if (isVirtual) { | ||
344 | mHal->destroyVirtualDisplay(display); | ||
345 | } else { | ||
346 | ALOGW("performing a final presentDisplay"); | ||
347 | |||
348 | std::vector<Layer> changedLayers; | ||
349 | std::vector<IComposerClient::Composition> compositionTypes; | ||
350 | uint32_t displayRequestMask = 0; | ||
351 | std::vector<Layer> requestedLayers; | ||
352 | std::vector<uint32_t> requestMasks; | ||
353 | mHal->validateDisplay(display, &changedLayers, &compositionTypes, | ||
354 | &displayRequestMask, &requestedLayers, &requestMasks); | ||
355 | |||
356 | mHal->acceptDisplayChanges(display); | ||
357 | |||
358 | int32_t presentFence = -1; | ||
359 | std::vector<Layer> releasedLayers; | ||
360 | std::vector<int32_t> releaseFences; | ||
361 | mHal->presentDisplay(display, &presentFence, &releasedLayers, &releaseFences); | ||
362 | if (presentFence >= 0) { | ||
363 | close(presentFence); | ||
364 | } | ||
365 | for (auto fence : releaseFences) { | ||
366 | if (fence >= 0) { | ||
367 | close(fence); | ||
368 | } | ||
369 | } | ||
370 | } | ||
371 | }); | ||
372 | |||
373 | mResources.reset(); | ||
374 | } | ||
375 | |||
376 | Hal* const mHal; | ||
377 | |||
378 | std::unique_ptr<ComposerResources> mResources; | ||
379 | |||
380 | std::mutex mCommandEngineMutex; | ||
381 | std::unique_ptr<ComposerCommandEngine> mCommandEngine; | ||
382 | |||
383 | std::function<void()> mOnClientDestroyed; | ||
384 | std::unique_ptr<HalEventCallback> mHalEventCallback; | ||
385 | }; | ||
386 | |||
387 | } // namespace detail | ||
388 | |||
389 | using ComposerClient = detail::ComposerClientImpl<IComposerClient, ComposerHal>; | ||
390 | |||
391 | } // namespace hal | ||
392 | } // namespace V2_1 | ||
393 | } // namespace composer | ||
394 | } // namespace graphics | ||
395 | } // namespace hardware | ||
396 | } // namespace android | ||
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h new file mode 100644 index 00000000..36aa64ef --- /dev/null +++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h | |||
@@ -0,0 +1,594 @@ | |||
1 | /* | ||
2 | * Copyright 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #pragma once | ||
18 | |||
19 | #ifndef LOG_TAG | ||
20 | #warning "ComposerCommandEngine.h included without LOG_TAG" | ||
21 | #endif | ||
22 | |||
23 | #include <vector> | ||
24 | |||
25 | #include <composer-command-buffer/2.1/ComposerCommandBuffer.h> | ||
26 | #include <composer-hal/2.1/ComposerHal.h> | ||
27 | #include <composer-hal/2.1/ComposerResources.h> | ||
28 | // TODO remove hwcomposer_defs.h dependency | ||
29 | #include <hardware/hwcomposer_defs.h> | ||
30 | #include <log/log.h> | ||
31 | |||
32 | namespace android { | ||
33 | namespace hardware { | ||
34 | namespace graphics { | ||
35 | namespace composer { | ||
36 | namespace V2_1 { | ||
37 | namespace hal { | ||
38 | |||
39 | // TODO own a CommandReaderBase rather than subclassing | ||
40 | class ComposerCommandEngine : protected CommandReaderBase { | ||
41 | public: | ||
42 | ComposerCommandEngine(ComposerHal* hal, ComposerResources* resources) | ||
43 | : mHal(hal), mResources(resources) {} | ||
44 | |||
45 | virtual ~ComposerCommandEngine() = default; | ||
46 | |||
47 | bool setInputMQDescriptor(const MQDescriptorSync<uint32_t>& descriptor) { | ||
48 | return setMQDescriptor(descriptor); | ||
49 | } | ||
50 | |||
51 | Error execute(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles, bool* outQueueChanged, | ||
52 | uint32_t* outCommandLength, hidl_vec<hidl_handle>* outCommandHandles) { | ||
53 | if (!readQueue(inLength, inHandles)) { | ||
54 | return Error::BAD_PARAMETER; | ||
55 | } | ||
56 | |||
57 | IComposerClient::Command command; | ||
58 | uint16_t length = 0; | ||
59 | while (!isEmpty()) { | ||
60 | if (!beginCommand(&command, &length)) { | ||
61 | break; | ||
62 | } | ||
63 | |||
64 | bool parsed = executeCommand(command, length); | ||
65 | endCommand(); | ||
66 | |||
67 | if (!parsed) { | ||
68 | ALOGE("failed to parse command 0x%x, length %" PRIu16, command, length); | ||
69 | break; | ||
70 | } | ||
71 | } | ||
72 | |||
73 | if (!isEmpty()) { | ||
74 | return Error::BAD_PARAMETER; | ||
75 | } | ||
76 | |||
77 | return mWriter.writeQueue(outQueueChanged, outCommandLength, outCommandHandles) | ||
78 | ? Error::NONE | ||
79 | : Error::NO_RESOURCES; | ||
80 | } | ||
81 | |||
82 | const MQDescriptorSync<uint32_t>* getOutputMQDescriptor() { return mWriter.getMQDescriptor(); } | ||
83 | |||
84 | void reset() { | ||
85 | CommandReaderBase::reset(); | ||
86 | mWriter.reset(); | ||
87 | } | ||
88 | |||
89 | protected: | ||
90 | virtual bool executeCommand(IComposerClient::Command command, uint16_t length) { | ||
91 | switch (command) { | ||
92 | case IComposerClient::Command::SELECT_DISPLAY: | ||
93 | return executeSelectDisplay(length); | ||
94 | case IComposerClient::Command::SELECT_LAYER: | ||
95 | return executeSelectLayer(length); | ||
96 | case IComposerClient::Command::SET_COLOR_TRANSFORM: | ||
97 | return executeSetColorTransform(length); | ||
98 | case IComposerClient::Command::SET_CLIENT_TARGET: | ||
99 | return executeSetClientTarget(length); | ||
100 | case IComposerClient::Command::SET_OUTPUT_BUFFER: | ||
101 | return executeSetOutputBuffer(length); | ||
102 | case IComposerClient::Command::VALIDATE_DISPLAY: | ||
103 | return executeValidateDisplay(length); | ||
104 | case IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY: | ||
105 | return executePresentOrValidateDisplay(length); | ||
106 | case IComposerClient::Command::ACCEPT_DISPLAY_CHANGES: | ||
107 | return executeAcceptDisplayChanges(length); | ||
108 | case IComposerClient::Command::PRESENT_DISPLAY: | ||
109 | return executePresentDisplay(length); | ||
110 | case IComposerClient::Command::SET_LAYER_CURSOR_POSITION: | ||
111 | return executeSetLayerCursorPosition(length); | ||
112 | case IComposerClient::Command::SET_LAYER_BUFFER: | ||
113 | return executeSetLayerBuffer(length); | ||
114 | case IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE: | ||
115 | return executeSetLayerSurfaceDamage(length); | ||
116 | case IComposerClient::Command::SET_LAYER_BLEND_MODE: | ||
117 | return executeSetLayerBlendMode(length); | ||
118 | case IComposerClient::Command::SET_LAYER_COLOR: | ||
119 | return executeSetLayerColor(length); | ||
120 | case IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE: | ||
121 | return executeSetLayerCompositionType(length); | ||
122 | case IComposerClient::Command::SET_LAYER_DATASPACE: | ||
123 | return executeSetLayerDataspace(length); | ||
124 | case IComposerClient::Command::SET_LAYER_DISPLAY_FRAME: | ||
125 | return executeSetLayerDisplayFrame(length); | ||
126 | case IComposerClient::Command::SET_LAYER_PLANE_ALPHA: | ||
127 | return executeSetLayerPlaneAlpha(length); | ||
128 | case IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM: | ||
129 | return executeSetLayerSidebandStream(length); | ||
130 | case IComposerClient::Command::SET_LAYER_SOURCE_CROP: | ||
131 | return executeSetLayerSourceCrop(length); | ||
132 | case IComposerClient::Command::SET_LAYER_TRANSFORM: | ||
133 | return executeSetLayerTransform(length); | ||
134 | case IComposerClient::Command::SET_LAYER_VISIBLE_REGION: | ||
135 | return executeSetLayerVisibleRegion(length); | ||
136 | case IComposerClient::Command::SET_LAYER_Z_ORDER: | ||
137 | return executeSetLayerZOrder(length); | ||
138 | default: | ||
139 | return false; | ||
140 | } | ||
141 | } | ||
142 | |||
143 | bool executeSelectDisplay(uint16_t length) { | ||
144 | if (length != CommandWriterBase::kSelectDisplayLength) { | ||
145 | return false; | ||
146 | } | ||
147 | |||
148 | mCurrentDisplay = read64(); | ||
149 | mWriter.selectDisplay(mCurrentDisplay); | ||
150 | |||
151 | return true; | ||
152 | } | ||
153 | |||
154 | bool executeSelectLayer(uint16_t length) { | ||
155 | if (length != CommandWriterBase::kSelectLayerLength) { | ||
156 | return false; | ||
157 | } | ||
158 | |||
159 | mCurrentLayer = read64(); | ||
160 | |||
161 | return true; | ||
162 | } | ||
163 | |||
164 | bool executeSetColorTransform(uint16_t length) { | ||
165 | if (length != CommandWriterBase::kSetColorTransformLength) { | ||
166 | return false; | ||
167 | } | ||
168 | |||
169 | float matrix[16]; | ||
170 | for (int i = 0; i < 16; i++) { | ||
171 | matrix[i] = readFloat(); | ||
172 | } | ||
173 | auto transform = readSigned(); | ||
174 | |||
175 | auto err = mHal->setColorTransform(mCurrentDisplay, matrix, transform); | ||
176 | if (err != Error::NONE) { | ||
177 | mWriter.setError(getCommandLoc(), err); | ||
178 | } | ||
179 | |||
180 | return true; | ||
181 | } | ||
182 | |||
183 | bool executeSetClientTarget(uint16_t length) { | ||
184 | // 4 parameters followed by N rectangles | ||
185 | if ((length - 4) % 4 != 0) { | ||
186 | return false; | ||
187 | } | ||
188 | |||
189 | bool useCache = false; | ||
190 | auto slot = read(); | ||
191 | auto rawHandle = readHandle(&useCache); | ||
192 | auto fence = readFence(); | ||
193 | auto dataspace = readSigned(); | ||
194 | auto damage = readRegion((length - 4) / 4); | ||
195 | bool closeFence = true; | ||
196 | |||
197 | const native_handle_t* clientTarget; | ||
198 | ComposerResources::ReplacedBufferHandle replacedClientTarget; | ||
199 | auto err = mResources->getDisplayClientTarget(mCurrentDisplay, slot, useCache, rawHandle, | ||
200 | &clientTarget, &replacedClientTarget); | ||
201 | if (err == Error::NONE) { | ||
202 | err = mHal->setClientTarget(mCurrentDisplay, clientTarget, fence, dataspace, damage); | ||
203 | if (err == Error::NONE) { | ||
204 | closeFence = false; | ||
205 | } | ||
206 | } | ||
207 | if (closeFence) { | ||
208 | close(fence); | ||
209 | } | ||
210 | if (err != Error::NONE) { | ||
211 | mWriter.setError(getCommandLoc(), err); | ||
212 | } | ||
213 | |||
214 | return true; | ||
215 | } | ||
216 | |||
217 | bool executeSetOutputBuffer(uint16_t length) { | ||
218 | if (length != CommandWriterBase::kSetOutputBufferLength) { | ||
219 | return false; | ||
220 | } | ||
221 | |||
222 | bool useCache = false; | ||
223 | auto slot = read(); | ||
224 | auto rawhandle = readHandle(&useCache); | ||
225 | auto fence = readFence(); | ||
226 | bool closeFence = true; | ||
227 | |||
228 | const native_handle_t* outputBuffer; | ||
229 | ComposerResources::ReplacedBufferHandle replacedOutputBuffer; | ||
230 | auto err = mResources->getDisplayOutputBuffer(mCurrentDisplay, slot, useCache, rawhandle, | ||
231 | &outputBuffer, &replacedOutputBuffer); | ||
232 | if (err == Error::NONE) { | ||
233 | err = mHal->setOutputBuffer(mCurrentDisplay, outputBuffer, fence); | ||
234 | if (err == Error::NONE) { | ||
235 | closeFence = false; | ||
236 | } | ||
237 | } | ||
238 | if (closeFence) { | ||
239 | close(fence); | ||
240 | } | ||
241 | if (err != Error::NONE) { | ||
242 | mWriter.setError(getCommandLoc(), err); | ||
243 | } | ||
244 | |||
245 | return true; | ||
246 | } | ||
247 | |||
248 | bool executeValidateDisplay(uint16_t length) { | ||
249 | if (length != CommandWriterBase::kValidateDisplayLength) { | ||
250 | return false; | ||
251 | } | ||
252 | |||
253 | std::vector<Layer> changedLayers; | ||
254 | std::vector<IComposerClient::Composition> compositionTypes; | ||
255 | uint32_t displayRequestMask = 0x0; | ||
256 | std::vector<Layer> requestedLayers; | ||
257 | std::vector<uint32_t> requestMasks; | ||
258 | |||
259 | auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes, | ||
260 | &displayRequestMask, &requestedLayers, &requestMasks); | ||
261 | if (err == Error::NONE) { | ||
262 | mWriter.setChangedCompositionTypes(changedLayers, compositionTypes); | ||
263 | mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks); | ||
264 | } else { | ||
265 | mWriter.setError(getCommandLoc(), err); | ||
266 | } | ||
267 | |||
268 | return true; | ||
269 | } | ||
270 | |||
271 | bool executePresentOrValidateDisplay(uint16_t length) { | ||
272 | if (length != CommandWriterBase::kPresentOrValidateDisplayLength) { | ||
273 | return false; | ||
274 | } | ||
275 | |||
276 | // First try to Present as is. | ||
277 | if (mHal->hasCapability(HWC2_CAPABILITY_SKIP_VALIDATE)) { | ||
278 | int presentFence = -1; | ||
279 | std::vector<Layer> layers; | ||
280 | std::vector<int> fences; | ||
281 | auto err = mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences); | ||
282 | if (err == Error::NONE) { | ||
283 | mWriter.setPresentOrValidateResult(1); | ||
284 | mWriter.setPresentFence(presentFence); | ||
285 | mWriter.setReleaseFences(layers, fences); | ||
286 | return true; | ||
287 | } | ||
288 | } | ||
289 | |||
290 | // Present has failed. We need to fallback to validate | ||
291 | std::vector<Layer> changedLayers; | ||
292 | std::vector<IComposerClient::Composition> compositionTypes; | ||
293 | uint32_t displayRequestMask = 0x0; | ||
294 | std::vector<Layer> requestedLayers; | ||
295 | std::vector<uint32_t> requestMasks; | ||
296 | |||
297 | auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes, | ||
298 | &displayRequestMask, &requestedLayers, &requestMasks); | ||
299 | if (err == Error::NONE) { | ||
300 | mWriter.setPresentOrValidateResult(0); | ||
301 | mWriter.setChangedCompositionTypes(changedLayers, compositionTypes); | ||
302 | mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks); | ||
303 | } else { | ||
304 | mWriter.setError(getCommandLoc(), err); | ||
305 | } | ||
306 | |||
307 | return true; | ||
308 | } | ||
309 | |||
310 | bool executeAcceptDisplayChanges(uint16_t length) { | ||
311 | if (length != CommandWriterBase::kAcceptDisplayChangesLength) { | ||
312 | return false; | ||
313 | } | ||
314 | |||
315 | auto err = mHal->acceptDisplayChanges(mCurrentDisplay); | ||
316 | if (err != Error::NONE) { | ||
317 | mWriter.setError(getCommandLoc(), err); | ||
318 | } | ||
319 | |||
320 | return true; | ||
321 | } | ||
322 | |||
323 | bool executePresentDisplay(uint16_t length) { | ||
324 | if (length != CommandWriterBase::kPresentDisplayLength) { | ||
325 | return false; | ||
326 | } | ||
327 | |||
328 | int presentFence = -1; | ||
329 | std::vector<Layer> layers; | ||
330 | std::vector<int> fences; | ||
331 | auto err = mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences); | ||
332 | if (err == Error::NONE) { | ||
333 | mWriter.setPresentFence(presentFence); | ||
334 | mWriter.setReleaseFences(layers, fences); | ||
335 | } else { | ||
336 | mWriter.setError(getCommandLoc(), err); | ||
337 | } | ||
338 | |||
339 | return true; | ||
340 | } | ||
341 | |||
342 | bool executeSetLayerCursorPosition(uint16_t length) { | ||
343 | if (length != CommandWriterBase::kSetLayerCursorPositionLength) { | ||
344 | return false; | ||
345 | } | ||
346 | |||
347 | auto err = mHal->setLayerCursorPosition(mCurrentDisplay, mCurrentLayer, readSigned(), | ||
348 | readSigned()); | ||
349 | if (err != Error::NONE) { | ||
350 | mWriter.setError(getCommandLoc(), err); | ||
351 | } | ||
352 | |||
353 | return true; | ||
354 | } | ||
355 | |||
356 | bool executeSetLayerBuffer(uint16_t length) { | ||
357 | if (length != CommandWriterBase::kSetLayerBufferLength) { | ||
358 | return false; | ||
359 | } | ||
360 | |||
361 | bool useCache = false; | ||
362 | auto slot = read(); | ||
363 | auto rawHandle = readHandle(&useCache); | ||
364 | auto fence = readFence(); | ||
365 | bool closeFence = true; | ||
366 | |||
367 | const native_handle_t* buffer; | ||
368 | ComposerResources::ReplacedBufferHandle replacedBuffer; | ||
369 | auto err = mResources->getLayerBuffer(mCurrentDisplay, mCurrentLayer, slot, useCache, | ||
370 | rawHandle, &buffer, &replacedBuffer); | ||
371 | if (err == Error::NONE) { | ||
372 | err = mHal->setLayerBuffer(mCurrentDisplay, mCurrentLayer, buffer, fence); | ||
373 | if (err == Error::NONE) { | ||
374 | closeFence = false; | ||
375 | } | ||
376 | } | ||
377 | if (closeFence) { | ||
378 | close(fence); | ||
379 | } | ||
380 | if (err != Error::NONE) { | ||
381 | mWriter.setError(getCommandLoc(), err); | ||
382 | } | ||
383 | |||
384 | return true; | ||
385 | } | ||
386 | |||
387 | bool executeSetLayerSurfaceDamage(uint16_t length) { | ||
388 | // N rectangles | ||
389 | if (length % 4 != 0) { | ||
390 | return false; | ||
391 | } | ||
392 | |||
393 | auto damage = readRegion(length / 4); | ||
394 | auto err = mHal->setLayerSurfaceDamage(mCurrentDisplay, mCurrentLayer, damage); | ||
395 | if (err != Error::NONE) { | ||
396 | mWriter.setError(getCommandLoc(), err); | ||
397 | } | ||
398 | |||
399 | return true; | ||
400 | } | ||
401 | |||
402 | bool executeSetLayerBlendMode(uint16_t length) { | ||
403 | if (length != CommandWriterBase::kSetLayerBlendModeLength) { | ||
404 | return false; | ||
405 | } | ||
406 | |||
407 | auto err = mHal->setLayerBlendMode(mCurrentDisplay, mCurrentLayer, readSigned()); | ||
408 | if (err != Error::NONE) { | ||
409 | mWriter.setError(getCommandLoc(), err); | ||
410 | } | ||
411 | |||
412 | return true; | ||
413 | } | ||
414 | |||
415 | bool executeSetLayerColor(uint16_t length) { | ||
416 | if (length != CommandWriterBase::kSetLayerColorLength) { | ||
417 | return false; | ||
418 | } | ||
419 | |||
420 | auto err = mHal->setLayerColor(mCurrentDisplay, mCurrentLayer, readColor()); | ||
421 | if (err != Error::NONE) { | ||
422 | mWriter.setError(getCommandLoc(), err); | ||
423 | } | ||
424 | |||
425 | return true; | ||
426 | } | ||
427 | |||
428 | bool executeSetLayerCompositionType(uint16_t length) { | ||
429 | if (length != CommandWriterBase::kSetLayerCompositionTypeLength) { | ||
430 | return false; | ||
431 | } | ||
432 | |||
433 | auto err = mHal->setLayerCompositionType(mCurrentDisplay, mCurrentLayer, readSigned()); | ||
434 | if (err != Error::NONE) { | ||
435 | mWriter.setError(getCommandLoc(), err); | ||
436 | } | ||
437 | |||
438 | return true; | ||
439 | } | ||
440 | |||
441 | bool executeSetLayerDataspace(uint16_t length) { | ||
442 | if (length != CommandWriterBase::kSetLayerDataspaceLength) { | ||
443 | return false; | ||
444 | } | ||
445 | |||
446 | auto err = mHal->setLayerDataspace(mCurrentDisplay, mCurrentLayer, readSigned()); | ||
447 | if (err != Error::NONE) { | ||
448 | mWriter.setError(getCommandLoc(), err); | ||
449 | } | ||
450 | |||
451 | return true; | ||
452 | } | ||
453 | |||
454 | bool executeSetLayerDisplayFrame(uint16_t length) { | ||
455 | if (length != CommandWriterBase::kSetLayerDisplayFrameLength) { | ||
456 | return false; | ||
457 | } | ||
458 | |||
459 | auto err = mHal->setLayerDisplayFrame(mCurrentDisplay, mCurrentLayer, readRect()); | ||
460 | if (err != Error::NONE) { | ||
461 | mWriter.setError(getCommandLoc(), err); | ||
462 | } | ||
463 | |||
464 | return true; | ||
465 | } | ||
466 | |||
467 | bool executeSetLayerPlaneAlpha(uint16_t length) { | ||
468 | if (length != CommandWriterBase::kSetLayerPlaneAlphaLength) { | ||
469 | return false; | ||
470 | } | ||
471 | |||
472 | auto err = mHal->setLayerPlaneAlpha(mCurrentDisplay, mCurrentLayer, readFloat()); | ||
473 | if (err != Error::NONE) { | ||
474 | mWriter.setError(getCommandLoc(), err); | ||
475 | } | ||
476 | |||
477 | return true; | ||
478 | } | ||
479 | |||
480 | bool executeSetLayerSidebandStream(uint16_t length) { | ||
481 | if (length != CommandWriterBase::kSetLayerSidebandStreamLength) { | ||
482 | return false; | ||
483 | } | ||
484 | |||
485 | auto rawHandle = readHandle(); | ||
486 | |||
487 | const native_handle_t* stream; | ||
488 | ComposerResources::ReplacedStreamHandle replacedStream; | ||
489 | auto err = mResources->getLayerSidebandStream(mCurrentDisplay, mCurrentLayer, rawHandle, | ||
490 | &stream, &replacedStream); | ||
491 | if (err == Error::NONE) { | ||
492 | err = mHal->setLayerSidebandStream(mCurrentDisplay, mCurrentLayer, stream); | ||
493 | } | ||
494 | if (err != Error::NONE) { | ||
495 | mWriter.setError(getCommandLoc(), err); | ||
496 | } | ||
497 | |||
498 | return true; | ||
499 | } | ||
500 | |||
501 | bool executeSetLayerSourceCrop(uint16_t length) { | ||
502 | if (length != CommandWriterBase::kSetLayerSourceCropLength) { | ||
503 | return false; | ||
504 | } | ||
505 | |||
506 | auto err = mHal->setLayerSourceCrop(mCurrentDisplay, mCurrentLayer, readFRect()); | ||
507 | if (err != Error::NONE) { | ||
508 | mWriter.setError(getCommandLoc(), err); | ||
509 | } | ||
510 | |||
511 | return true; | ||
512 | } | ||
513 | |||
514 | bool executeSetLayerTransform(uint16_t length) { | ||
515 | if (length != CommandWriterBase::kSetLayerTransformLength) { | ||
516 | return false; | ||
517 | } | ||
518 | |||
519 | auto err = mHal->setLayerTransform(mCurrentDisplay, mCurrentLayer, readSigned()); | ||
520 | if (err != Error::NONE) { | ||
521 | mWriter.setError(getCommandLoc(), err); | ||
522 | } | ||
523 | |||
524 | return true; | ||
525 | } | ||
526 | |||
527 | bool executeSetLayerVisibleRegion(uint16_t length) { | ||
528 | // N rectangles | ||
529 | if (length % 4 != 0) { | ||
530 | return false; | ||
531 | } | ||
532 | |||
533 | auto region = readRegion(length / 4); | ||
534 | auto err = mHal->setLayerVisibleRegion(mCurrentDisplay, mCurrentLayer, region); | ||
535 | if (err != Error::NONE) { | ||
536 | mWriter.setError(getCommandLoc(), err); | ||
537 | } | ||
538 | |||
539 | return true; | ||
540 | } | ||
541 | |||
542 | bool executeSetLayerZOrder(uint16_t length) { | ||
543 | if (length != CommandWriterBase::kSetLayerZOrderLength) { | ||
544 | return false; | ||
545 | } | ||
546 | |||
547 | auto err = mHal->setLayerZOrder(mCurrentDisplay, mCurrentLayer, read()); | ||
548 | if (err != Error::NONE) { | ||
549 | mWriter.setError(getCommandLoc(), err); | ||
550 | } | ||
551 | |||
552 | return true; | ||
553 | } | ||
554 | |||
555 | hwc_rect_t readRect() { | ||
556 | return hwc_rect_t{ | ||
557 | readSigned(), readSigned(), readSigned(), readSigned(), | ||
558 | }; | ||
559 | } | ||
560 | |||
561 | std::vector<hwc_rect_t> readRegion(size_t count) { | ||
562 | std::vector<hwc_rect_t> region; | ||
563 | region.reserve(count); | ||
564 | while (count > 0) { | ||
565 | region.emplace_back(readRect()); | ||
566 | count--; | ||
567 | } | ||
568 | |||
569 | return region; | ||
570 | } | ||
571 | |||
572 | hwc_frect_t readFRect() { | ||
573 | return hwc_frect_t{ | ||
574 | readFloat(), readFloat(), readFloat(), readFloat(), | ||
575 | }; | ||
576 | } | ||
577 | |||
578 | ComposerHal* mHal; | ||
579 | ComposerResources* mResources; | ||
580 | |||
581 | // 64KiB minus a small space for metadata such as read/write pointers | ||
582 | static constexpr size_t kWriterInitialSize = 64 * 1024 / sizeof(uint32_t) - 16; | ||
583 | CommandWriterBase mWriter{kWriterInitialSize}; | ||
584 | |||
585 | Display mCurrentDisplay = 0; | ||
586 | Layer mCurrentLayer = 0; | ||
587 | }; | ||
588 | |||
589 | } // namespace hal | ||
590 | } // namespace V2_1 | ||
591 | } // namespace composer | ||
592 | } // namespace graphics | ||
593 | } // namespace hardware | ||
594 | } // namespace android | ||
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h new file mode 100644 index 00000000..c9793fd9 --- /dev/null +++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerHal.h | |||
@@ -0,0 +1,137 @@ | |||
1 | /* | ||
2 | * Copyright 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #pragma once | ||
18 | |||
19 | #include <string> | ||
20 | #include <vector> | ||
21 | |||
22 | #include <android/hardware/graphics/composer/2.1/IComposer.h> | ||
23 | #include <android/hardware/graphics/composer/2.1/IComposerClient.h> | ||
24 | |||
25 | // TODO remove hwcomposer2.h dependency | ||
26 | #define HWC2_INCLUDE_STRINGIFICATION | ||
27 | #define HWC2_USE_CPP11 | ||
28 | #include <hardware/hwcomposer2.h> | ||
29 | #undef HWC2_INCLUDE_STRINGIFICATION | ||
30 | #undef HWC2_USE_CPP11 | ||
31 | |||
32 | namespace android { | ||
33 | namespace hardware { | ||
34 | namespace graphics { | ||
35 | namespace composer { | ||
36 | namespace V2_1 { | ||
37 | namespace hal { | ||
38 | |||
39 | using common::V1_0::ColorMode; | ||
40 | using common::V1_0::ColorTransform; | ||
41 | using common::V1_0::Dataspace; | ||
42 | using common::V1_0::Hdr; | ||
43 | using common::V1_0::PixelFormat; | ||
44 | using common::V1_0::Transform; | ||
45 | |||
46 | class ComposerHal { | ||
47 | public: | ||
48 | virtual ~ComposerHal() = default; | ||
49 | |||
50 | virtual bool hasCapability(hwc2_capability_t capability) = 0; | ||
51 | |||
52 | // dump the debug information | ||
53 | virtual std::string dumpDebugInfo() = 0; | ||
54 | |||
55 | class EventCallback { | ||
56 | public: | ||
57 | virtual ~EventCallback() = default; | ||
58 | virtual void onHotplug(Display display, IComposerCallback::Connection connected) = 0; | ||
59 | virtual void onRefresh(Display display) = 0; | ||
60 | virtual void onVsync(Display display, int64_t timestamp) = 0; | ||
61 | }; | ||
62 | |||
63 | // Register the event callback object. The event callback object is valid | ||
64 | // until it is unregistered. A hotplug event must be generated for each | ||
65 | // connected physical display, before or after this function returns. | ||
66 | virtual void registerEventCallback(EventCallback* callback) = 0; | ||
67 | |||
68 | // Unregister the event callback object. It must block if there is any | ||
69 | // callback in-flight. | ||
70 | virtual void unregisterEventCallback() = 0; | ||
71 | |||
72 | virtual uint32_t getMaxVirtualDisplayCount() = 0; | ||
73 | virtual Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format, | ||
74 | Display* outDisplay) = 0; | ||
75 | virtual Error destroyVirtualDisplay(Display display) = 0; | ||
76 | virtual Error createLayer(Display display, Layer* outLayer) = 0; | ||
77 | virtual Error destroyLayer(Display display, Layer layer) = 0; | ||
78 | |||
79 | virtual Error getActiveConfig(Display display, Config* outConfig) = 0; | ||
80 | virtual Error getClientTargetSupport(Display display, uint32_t width, uint32_t height, | ||
81 | PixelFormat format, Dataspace dataspace) = 0; | ||
82 | virtual Error getColorModes(Display display, hidl_vec<ColorMode>* outModes) = 0; | ||
83 | virtual Error getDisplayAttribute(Display display, Config config, | ||
84 | IComposerClient::Attribute attribute, int32_t* outValue) = 0; | ||
85 | virtual Error getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs) = 0; | ||
86 | virtual Error getDisplayName(Display display, hidl_string* outName) = 0; | ||
87 | virtual Error getDisplayType(Display display, IComposerClient::DisplayType* outType) = 0; | ||
88 | virtual Error getDozeSupport(Display display, bool* outSupport) = 0; | ||
89 | virtual Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes, | ||
90 | float* outMaxLuminance, float* outMaxAverageLuminance, | ||
91 | float* outMinLuminance) = 0; | ||
92 | |||
93 | virtual Error setActiveConfig(Display display, Config config) = 0; | ||
94 | virtual Error setColorMode(Display display, ColorMode mode) = 0; | ||
95 | virtual Error setPowerMode(Display display, IComposerClient::PowerMode mode) = 0; | ||
96 | virtual Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled) = 0; | ||
97 | |||
98 | virtual Error setColorTransform(Display display, const float* matrix, int32_t hint) = 0; | ||
99 | virtual Error setClientTarget(Display display, buffer_handle_t target, int32_t acquireFence, | ||
100 | int32_t dataspace, const std::vector<hwc_rect_t>& damage) = 0; | ||
101 | virtual Error setOutputBuffer(Display display, buffer_handle_t buffer, | ||
102 | int32_t releaseFence) = 0; | ||
103 | virtual Error validateDisplay(Display display, std::vector<Layer>* outChangedLayers, | ||
104 | std::vector<IComposerClient::Composition>* outCompositionTypes, | ||
105 | uint32_t* outDisplayRequestMask, | ||
106 | std::vector<Layer>* outRequestedLayers, | ||
107 | std::vector<uint32_t>* outRequestMasks) = 0; | ||
108 | virtual Error acceptDisplayChanges(Display display) = 0; | ||
109 | virtual Error presentDisplay(Display display, int32_t* outPresentFence, | ||
110 | std::vector<Layer>* outLayers, | ||
111 | std::vector<int32_t>* outReleaseFences) = 0; | ||
112 | |||
113 | virtual Error setLayerCursorPosition(Display display, Layer layer, int32_t x, int32_t y) = 0; | ||
114 | virtual Error setLayerBuffer(Display display, Layer layer, buffer_handle_t buffer, | ||
115 | int32_t acquireFence) = 0; | ||
116 | virtual Error setLayerSurfaceDamage(Display display, Layer layer, | ||
117 | const std::vector<hwc_rect_t>& damage) = 0; | ||
118 | virtual Error setLayerBlendMode(Display display, Layer layer, int32_t mode) = 0; | ||
119 | virtual Error setLayerColor(Display display, Layer layer, IComposerClient::Color color) = 0; | ||
120 | virtual Error setLayerCompositionType(Display display, Layer layer, int32_t type) = 0; | ||
121 | virtual Error setLayerDataspace(Display display, Layer layer, int32_t dataspace) = 0; | ||
122 | virtual Error setLayerDisplayFrame(Display display, Layer layer, const hwc_rect_t& frame) = 0; | ||
123 | virtual Error setLayerPlaneAlpha(Display display, Layer layer, float alpha) = 0; | ||
124 | virtual Error setLayerSidebandStream(Display display, Layer layer, buffer_handle_t stream) = 0; | ||
125 | virtual Error setLayerSourceCrop(Display display, Layer layer, const hwc_frect_t& crop) = 0; | ||
126 | virtual Error setLayerTransform(Display display, Layer layer, int32_t transform) = 0; | ||
127 | virtual Error setLayerVisibleRegion(Display display, Layer layer, | ||
128 | const std::vector<hwc_rect_t>& visible) = 0; | ||
129 | virtual Error setLayerZOrder(Display display, Layer layer, uint32_t z) = 0; | ||
130 | }; | ||
131 | |||
132 | } // namespace hal | ||
133 | } // namespace V2_1 | ||
134 | } // namespace composer | ||
135 | } // namespace graphics | ||
136 | } // namespace hardware | ||
137 | } // namespace android | ||
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h new file mode 100644 index 00000000..7bb36929 --- /dev/null +++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h | |||
@@ -0,0 +1,536 @@ | |||
1 | /* | ||
2 | * Copyright 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #pragma once | ||
18 | |||
19 | #ifndef LOG_TAG | ||
20 | #warning "ComposerResources.h included without LOG_TAG" | ||
21 | #endif | ||
22 | |||
23 | #include <memory> | ||
24 | #include <mutex> | ||
25 | #include <unordered_map> | ||
26 | #include <vector> | ||
27 | |||
28 | #include <android/hardware/graphics/mapper/2.0/IMapper.h> | ||
29 | #include <log/log.h> | ||
30 | |||
31 | namespace android { | ||
32 | namespace hardware { | ||
33 | namespace graphics { | ||
34 | namespace composer { | ||
35 | namespace V2_1 { | ||
36 | namespace hal { | ||
37 | |||
38 | // wrapper for IMapper to import buffers and sideband streams | ||
39 | class ComposerHandleImporter { | ||
40 | public: | ||
41 | bool init() { | ||
42 | mMapper = mapper::V2_0::IMapper::getService(); | ||
43 | ALOGE_IF(!mMapper, "failed to get mapper service"); | ||
44 | return mMapper != nullptr; | ||
45 | } | ||
46 | |||
47 | Error importBuffer(const native_handle_t* rawHandle, const native_handle_t** outBufferHandle) { | ||
48 | if (!rawHandle || (!rawHandle->numFds && !rawHandle->numInts)) { | ||
49 | *outBufferHandle = nullptr; | ||
50 | return Error::NONE; | ||
51 | } | ||
52 | |||
53 | mapper::V2_0::Error error; | ||
54 | const native_handle_t* bufferHandle; | ||
55 | mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) { | ||
56 | error = tmpError; | ||
57 | bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle); | ||
58 | }); | ||
59 | if (error != mapper::V2_0::Error::NONE) { | ||
60 | return Error::NO_RESOURCES; | ||
61 | } | ||
62 | |||
63 | *outBufferHandle = bufferHandle; | ||
64 | return Error::NONE; | ||
65 | } | ||
66 | |||
67 | void freeBuffer(const native_handle_t* bufferHandle) { | ||
68 | if (bufferHandle) { | ||
69 | mMapper->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle))); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | Error importStream(const native_handle_t* rawHandle, const native_handle_t** outStreamHandle) { | ||
74 | const native_handle_t* streamHandle = nullptr; | ||
75 | if (rawHandle) { | ||
76 | streamHandle = native_handle_clone(rawHandle); | ||
77 | if (!streamHandle) { | ||
78 | return Error::NO_RESOURCES; | ||
79 | } | ||
80 | } | ||
81 | |||
82 | *outStreamHandle = streamHandle; | ||
83 | return Error::NONE; | ||
84 | } | ||
85 | |||
86 | void freeStream(const native_handle_t* streamHandle) { | ||
87 | if (streamHandle) { | ||
88 | native_handle_close(streamHandle); | ||
89 | native_handle_delete(const_cast<native_handle_t*>(streamHandle)); | ||
90 | } | ||
91 | } | ||
92 | |||
93 | private: | ||
94 | sp<mapper::V2_0::IMapper> mMapper; | ||
95 | }; | ||
96 | |||
97 | class ComposerHandleCache { | ||
98 | public: | ||
99 | enum class HandleType { | ||
100 | INVALID, | ||
101 | BUFFER, | ||
102 | STREAM, | ||
103 | }; | ||
104 | |||
105 | ComposerHandleCache(ComposerHandleImporter& importer, HandleType type, uint32_t cacheSize) | ||
106 | : mImporter(importer), mHandleType(type), mHandles(cacheSize, nullptr) {} | ||
107 | |||
108 | // must be initialized later with initCache | ||
109 | ComposerHandleCache(ComposerHandleImporter& importer) : mImporter(importer) {} | ||
110 | |||
111 | ~ComposerHandleCache() { | ||
112 | switch (mHandleType) { | ||
113 | case HandleType::BUFFER: | ||
114 | for (auto handle : mHandles) { | ||
115 | mImporter.freeBuffer(handle); | ||
116 | } | ||
117 | break; | ||
118 | case HandleType::STREAM: | ||
119 | for (auto handle : mHandles) { | ||
120 | mImporter.freeStream(handle); | ||
121 | } | ||
122 | break; | ||
123 | default: | ||
124 | break; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | ComposerHandleCache(const ComposerHandleCache&) = delete; | ||
129 | ComposerHandleCache& operator=(const ComposerHandleCache&) = delete; | ||
130 | |||
131 | bool initCache(HandleType type, uint32_t cacheSize) { | ||
132 | // already initialized | ||
133 | if (mHandleType != HandleType::INVALID) { | ||
134 | return false; | ||
135 | } | ||
136 | |||
137 | mHandleType = type; | ||
138 | mHandles.resize(cacheSize, nullptr); | ||
139 | |||
140 | return true; | ||
141 | } | ||
142 | |||
143 | Error lookupCache(uint32_t slot, const native_handle_t** outHandle) { | ||
144 | if (slot < mHandles.size()) { | ||
145 | *outHandle = mHandles[slot]; | ||
146 | return Error::NONE; | ||
147 | } else { | ||
148 | return Error::BAD_PARAMETER; | ||
149 | } | ||
150 | } | ||
151 | |||
152 | Error updateCache(uint32_t slot, const native_handle_t* handle, | ||
153 | const native_handle** outReplacedHandle) { | ||
154 | if (slot < mHandles.size()) { | ||
155 | auto& cachedHandle = mHandles[slot]; | ||
156 | *outReplacedHandle = cachedHandle; | ||
157 | cachedHandle = handle; | ||
158 | return Error::NONE; | ||
159 | } else { | ||
160 | return Error::BAD_PARAMETER; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | // when fromCache is true, look up in the cache; otherwise, update the cache | ||
165 | Error getHandle(uint32_t slot, bool fromCache, const native_handle_t* inHandle, | ||
166 | const native_handle_t** outHandle, const native_handle** outReplacedHandle) { | ||
167 | if (fromCache) { | ||
168 | *outReplacedHandle = nullptr; | ||
169 | return lookupCache(slot, outHandle); | ||
170 | } else { | ||
171 | *outHandle = inHandle; | ||
172 | return updateCache(slot, inHandle, outReplacedHandle); | ||
173 | } | ||
174 | } | ||
175 | |||
176 | private: | ||
177 | ComposerHandleImporter& mImporter; | ||
178 | HandleType mHandleType = HandleType::INVALID; | ||
179 | std::vector<const native_handle_t*> mHandles; | ||
180 | }; | ||
181 | |||
182 | // layer resource | ||
183 | class ComposerLayerResource { | ||
184 | public: | ||
185 | ComposerLayerResource(ComposerHandleImporter& importer, uint32_t bufferCacheSize) | ||
186 | : mBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, bufferCacheSize), | ||
187 | mSidebandStreamCache(importer, ComposerHandleCache::HandleType::STREAM, 1) {} | ||
188 | |||
189 | Error getBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle, | ||
190 | const native_handle_t** outHandle, const native_handle** outReplacedHandle) { | ||
191 | return mBufferCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle); | ||
192 | } | ||
193 | |||
194 | Error getSidebandStream(uint32_t slot, bool fromCache, const native_handle_t* inHandle, | ||
195 | const native_handle_t** outHandle, | ||
196 | const native_handle** outReplacedHandle) { | ||
197 | return mSidebandStreamCache.getHandle(slot, fromCache, inHandle, outHandle, | ||
198 | outReplacedHandle); | ||
199 | } | ||
200 | |||
201 | protected: | ||
202 | ComposerHandleCache mBufferCache; | ||
203 | ComposerHandleCache mSidebandStreamCache; | ||
204 | }; | ||
205 | |||
206 | // display resource | ||
207 | class ComposerDisplayResource { | ||
208 | public: | ||
209 | enum class DisplayType { | ||
210 | PHYSICAL, | ||
211 | VIRTUAL, | ||
212 | }; | ||
213 | |||
214 | ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer, | ||
215 | uint32_t outputBufferCacheSize) | ||
216 | : mType(type), | ||
217 | mClientTargetCache(importer), | ||
218 | mOutputBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, | ||
219 | outputBufferCacheSize) {} | ||
220 | |||
221 | bool initClientTargetCache(uint32_t cacheSize) { | ||
222 | return mClientTargetCache.initCache(ComposerHandleCache::HandleType::BUFFER, cacheSize); | ||
223 | } | ||
224 | |||
225 | bool isVirtual() const { return mType == DisplayType::VIRTUAL; } | ||
226 | |||
227 | Error getClientTarget(uint32_t slot, bool fromCache, const native_handle_t* inHandle, | ||
228 | const native_handle_t** outHandle, | ||
229 | const native_handle** outReplacedHandle) { | ||
230 | return mClientTargetCache.getHandle(slot, fromCache, inHandle, outHandle, | ||
231 | outReplacedHandle); | ||
232 | } | ||
233 | |||
234 | Error getOutputBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle, | ||
235 | const native_handle_t** outHandle, | ||
236 | const native_handle** outReplacedHandle) { | ||
237 | return mOutputBufferCache.getHandle(slot, fromCache, inHandle, outHandle, | ||
238 | outReplacedHandle); | ||
239 | } | ||
240 | |||
241 | bool addLayer(Layer layer, std::unique_ptr<ComposerLayerResource> layerResource) { | ||
242 | auto result = mLayerResources.emplace(layer, std::move(layerResource)); | ||
243 | return result.second; | ||
244 | } | ||
245 | |||
246 | bool removeLayer(Layer layer) { return mLayerResources.erase(layer) > 0; } | ||
247 | |||
248 | ComposerLayerResource* findLayerResource(Layer layer) { | ||
249 | auto layerIter = mLayerResources.find(layer); | ||
250 | if (layerIter == mLayerResources.end()) { | ||
251 | return nullptr; | ||
252 | } | ||
253 | |||
254 | return layerIter->second.get(); | ||
255 | } | ||
256 | |||
257 | std::vector<Layer> getLayers() const { | ||
258 | std::vector<Layer> layers; | ||
259 | layers.reserve(mLayerResources.size()); | ||
260 | for (const auto& layerKey : mLayerResources) { | ||
261 | layers.push_back(layerKey.first); | ||
262 | } | ||
263 | return layers; | ||
264 | } | ||
265 | |||
266 | protected: | ||
267 | const DisplayType mType; | ||
268 | ComposerHandleCache mClientTargetCache; | ||
269 | ComposerHandleCache mOutputBufferCache; | ||
270 | |||
271 | std::unordered_map<Layer, std::unique_ptr<ComposerLayerResource>> mLayerResources; | ||
272 | }; | ||
273 | |||
274 | class ComposerResources { | ||
275 | private: | ||
276 | template <bool isBuffer> | ||
277 | class ReplacedHandle; | ||
278 | |||
279 | public: | ||
280 | static std::unique_ptr<ComposerResources> create() { | ||
281 | auto resources = std::make_unique<ComposerResources>(); | ||
282 | return resources->init() ? std::move(resources) : nullptr; | ||
283 | } | ||
284 | |||
285 | ComposerResources() = default; | ||
286 | virtual ~ComposerResources() = default; | ||
287 | |||
288 | bool init() { return mImporter.init(); } | ||
289 | |||
290 | using RemoveDisplay = | ||
291 | std::function<void(Display display, bool isVirtual, const std::vector<Layer>& layers)>; | ||
292 | void clear(RemoveDisplay removeDisplay) { | ||
293 | std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); | ||
294 | for (const auto& displayKey : mDisplayResources) { | ||
295 | Display display = displayKey.first; | ||
296 | const ComposerDisplayResource& displayResource = *displayKey.second; | ||
297 | removeDisplay(display, displayResource.isVirtual(), displayResource.getLayers()); | ||
298 | } | ||
299 | mDisplayResources.clear(); | ||
300 | } | ||
301 | |||
302 | Error addPhysicalDisplay(Display display) { | ||
303 | auto displayResource = | ||
304 | createDisplayResource(ComposerDisplayResource::DisplayType::PHYSICAL, 0); | ||
305 | |||
306 | std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); | ||
307 | auto result = mDisplayResources.emplace(display, std::move(displayResource)); | ||
308 | return result.second ? Error::NONE : Error::BAD_DISPLAY; | ||
309 | } | ||
310 | |||
311 | Error addVirtualDisplay(Display display, uint32_t outputBufferCacheSize) { | ||
312 | auto displayResource = createDisplayResource(ComposerDisplayResource::DisplayType::VIRTUAL, | ||
313 | outputBufferCacheSize); | ||
314 | |||
315 | std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); | ||
316 | auto result = mDisplayResources.emplace(display, std::move(displayResource)); | ||
317 | return result.second ? Error::NONE : Error::BAD_DISPLAY; | ||
318 | } | ||
319 | |||
320 | Error removeDisplay(Display display) { | ||
321 | std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); | ||
322 | return mDisplayResources.erase(display) > 0 ? Error::NONE : Error::BAD_DISPLAY; | ||
323 | } | ||
324 | |||
325 | Error setDisplayClientTargetCacheSize(Display display, uint32_t clientTargetCacheSize) { | ||
326 | std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); | ||
327 | ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); | ||
328 | if (!displayResource) { | ||
329 | return Error::BAD_DISPLAY; | ||
330 | } | ||
331 | |||
332 | return displayResource->initClientTargetCache(clientTargetCacheSize) ? Error::NONE | ||
333 | : Error::BAD_PARAMETER; | ||
334 | } | ||
335 | |||
336 | Error addLayer(Display display, Layer layer, uint32_t bufferCacheSize) { | ||
337 | auto layerResource = createLayerResource(bufferCacheSize); | ||
338 | |||
339 | std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); | ||
340 | ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); | ||
341 | if (!displayResource) { | ||
342 | return Error::BAD_DISPLAY; | ||
343 | } | ||
344 | |||
345 | return displayResource->addLayer(layer, std::move(layerResource)) ? Error::NONE | ||
346 | : Error::BAD_LAYER; | ||
347 | } | ||
348 | |||
349 | Error removeLayer(Display display, Layer layer) { | ||
350 | std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); | ||
351 | ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); | ||
352 | if (!displayResource) { | ||
353 | return Error::BAD_DISPLAY; | ||
354 | } | ||
355 | |||
356 | return displayResource->removeLayer(layer) ? Error::NONE : Error::BAD_LAYER; | ||
357 | } | ||
358 | |||
359 | using ReplacedBufferHandle = ReplacedHandle<true>; | ||
360 | using ReplacedStreamHandle = ReplacedHandle<false>; | ||
361 | |||
362 | Error getDisplayClientTarget(Display display, uint32_t slot, bool fromCache, | ||
363 | const native_handle_t* rawHandle, | ||
364 | const native_handle_t** outBufferHandle, | ||
365 | ReplacedBufferHandle* outReplacedBuffer) { | ||
366 | return getHandle<Cache::CLIENT_TARGET>(display, 0, slot, fromCache, rawHandle, | ||
367 | outBufferHandle, outReplacedBuffer); | ||
368 | } | ||
369 | |||
370 | Error getDisplayOutputBuffer(Display display, uint32_t slot, bool fromCache, | ||
371 | const native_handle_t* rawHandle, | ||
372 | const native_handle_t** outBufferHandle, | ||
373 | ReplacedBufferHandle* outReplacedBuffer) { | ||
374 | return getHandle<Cache::OUTPUT_BUFFER>(display, 0, slot, fromCache, rawHandle, | ||
375 | outBufferHandle, outReplacedBuffer); | ||
376 | } | ||
377 | |||
378 | Error getLayerBuffer(Display display, Layer layer, uint32_t slot, bool fromCache, | ||
379 | const native_handle_t* rawHandle, const native_handle_t** outBufferHandle, | ||
380 | ReplacedBufferHandle* outReplacedBuffer) { | ||
381 | return getHandle<Cache::LAYER_BUFFER>(display, layer, slot, fromCache, rawHandle, | ||
382 | outBufferHandle, outReplacedBuffer); | ||
383 | } | ||
384 | |||
385 | Error getLayerSidebandStream(Display display, Layer layer, const native_handle_t* rawHandle, | ||
386 | const native_handle_t** outStreamHandle, | ||
387 | ReplacedStreamHandle* outReplacedStream) { | ||
388 | return getHandle<Cache::LAYER_SIDEBAND_STREAM>(display, layer, 0, false, rawHandle, | ||
389 | outStreamHandle, outReplacedStream); | ||
390 | } | ||
391 | |||
392 | protected: | ||
393 | virtual std::unique_ptr<ComposerDisplayResource> createDisplayResource( | ||
394 | ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) { | ||
395 | return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize); | ||
396 | } | ||
397 | |||
398 | virtual std::unique_ptr<ComposerLayerResource> createLayerResource(uint32_t bufferCacheSize) { | ||
399 | return std::make_unique<ComposerLayerResource>(mImporter, bufferCacheSize); | ||
400 | } | ||
401 | |||
402 | ComposerDisplayResource* findDisplayResourceLocked(Display display) { | ||
403 | auto iter = mDisplayResources.find(display); | ||
404 | if (iter == mDisplayResources.end()) { | ||
405 | return nullptr; | ||
406 | } | ||
407 | return iter->second.get(); | ||
408 | } | ||
409 | |||
410 | ComposerHandleImporter mImporter; | ||
411 | |||
412 | std::mutex mDisplayResourcesMutex; | ||
413 | std::unordered_map<Display, std::unique_ptr<ComposerDisplayResource>> mDisplayResources; | ||
414 | |||
415 | private: | ||
416 | enum class Cache { | ||
417 | CLIENT_TARGET, | ||
418 | OUTPUT_BUFFER, | ||
419 | LAYER_BUFFER, | ||
420 | LAYER_SIDEBAND_STREAM, | ||
421 | }; | ||
422 | |||
423 | // When a buffer in the cache is replaced by a new one, we must keep it | ||
424 | // alive until it has been replaced in ComposerHal. | ||
425 | template <bool isBuffer> | ||
426 | class ReplacedHandle { | ||
427 | public: | ||
428 | ReplacedHandle() = default; | ||
429 | ReplacedHandle(const ReplacedHandle&) = delete; | ||
430 | ReplacedHandle& operator=(const ReplacedHandle&) = delete; | ||
431 | |||
432 | ~ReplacedHandle() { reset(); } | ||
433 | |||
434 | void reset(ComposerHandleImporter* importer = nullptr, | ||
435 | const native_handle_t* handle = nullptr) { | ||
436 | if (mHandle) { | ||
437 | if (isBuffer) { | ||
438 | mImporter->freeBuffer(mHandle); | ||
439 | } else { | ||
440 | mImporter->freeStream(mHandle); | ||
441 | } | ||
442 | } | ||
443 | |||
444 | mImporter = importer; | ||
445 | mHandle = handle; | ||
446 | } | ||
447 | |||
448 | private: | ||
449 | ComposerHandleImporter* mImporter = nullptr; | ||
450 | const native_handle_t* mHandle = nullptr; | ||
451 | }; | ||
452 | |||
453 | template <Cache cache, bool isBuffer> | ||
454 | Error getHandle(Display display, Layer layer, uint32_t slot, bool fromCache, | ||
455 | const native_handle_t* rawHandle, const native_handle_t** outHandle, | ||
456 | ReplacedHandle<isBuffer>* outReplacedHandle) { | ||
457 | Error error; | ||
458 | |||
459 | // import the raw handle (or ignore raw handle when fromCache is true) | ||
460 | const native_handle_t* importedHandle = nullptr; | ||
461 | if (!fromCache) { | ||
462 | error = (isBuffer) ? mImporter.importBuffer(rawHandle, &importedHandle) | ||
463 | : mImporter.importStream(rawHandle, &importedHandle); | ||
464 | if (error != Error::NONE) { | ||
465 | return error; | ||
466 | } | ||
467 | } | ||
468 | |||
469 | std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); | ||
470 | |||
471 | // find display/layer resource | ||
472 | const bool needLayerResource = | ||
473 | (cache == Cache::LAYER_BUFFER || cache == Cache::LAYER_SIDEBAND_STREAM); | ||
474 | ComposerDisplayResource* displayResource = findDisplayResourceLocked(display); | ||
475 | ComposerLayerResource* layerResource = (displayResource && needLayerResource) | ||
476 | ? displayResource->findLayerResource(layer) | ||
477 | : nullptr; | ||
478 | |||
479 | // lookup or update cache | ||
480 | const native_handle_t* replacedHandle = nullptr; | ||
481 | if (displayResource && (!needLayerResource || layerResource)) { | ||
482 | switch (cache) { | ||
483 | case Cache::CLIENT_TARGET: | ||
484 | error = displayResource->getClientTarget(slot, fromCache, importedHandle, | ||
485 | outHandle, &replacedHandle); | ||
486 | break; | ||
487 | case Cache::OUTPUT_BUFFER: | ||
488 | error = displayResource->getOutputBuffer(slot, fromCache, importedHandle, | ||
489 | outHandle, &replacedHandle); | ||
490 | break; | ||
491 | case Cache::LAYER_BUFFER: | ||
492 | error = layerResource->getBuffer(slot, fromCache, importedHandle, outHandle, | ||
493 | &replacedHandle); | ||
494 | break; | ||
495 | case Cache::LAYER_SIDEBAND_STREAM: | ||
496 | error = layerResource->getSidebandStream(slot, fromCache, importedHandle, | ||
497 | outHandle, &replacedHandle); | ||
498 | break; | ||
499 | default: | ||
500 | error = Error::BAD_PARAMETER; | ||
501 | break; | ||
502 | } | ||
503 | |||
504 | if (error != Error::NONE) { | ||
505 | ALOGW("invalid cache %d slot %d", int(cache), int(slot)); | ||
506 | } | ||
507 | } else if (!displayResource) { | ||
508 | error = Error::BAD_DISPLAY; | ||
509 | } else { | ||
510 | error = Error::BAD_LAYER; | ||
511 | } | ||
512 | |||
513 | // clean up on errors | ||
514 | if (error != Error::NONE) { | ||
515 | if (!fromCache) { | ||
516 | if (isBuffer) { | ||
517 | mImporter.freeBuffer(importedHandle); | ||
518 | } else { | ||
519 | mImporter.freeStream(importedHandle); | ||
520 | } | ||
521 | } | ||
522 | return error; | ||
523 | } | ||
524 | |||
525 | outReplacedHandle->reset(&mImporter, replacedHandle); | ||
526 | |||
527 | return Error::NONE; | ||
528 | } | ||
529 | }; | ||
530 | |||
531 | } // namespace hal | ||
532 | } // namespace V2_1 | ||
533 | } // namespace composer | ||
534 | } // namespace graphics | ||
535 | } // namespace hardware | ||
536 | } // namespace android | ||
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp b/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp new file mode 100644 index 00000000..420a1f60 --- /dev/null +++ b/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp | |||
@@ -0,0 +1,76 @@ | |||
1 | // Copyright 2010 The Android Open Source Project | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | cc_library_shared { | ||
16 | name: "libhwc2on1adapter", | ||
17 | vendor: true, | ||
18 | |||
19 | clang: true, | ||
20 | cflags: [ | ||
21 | "-Wall", | ||
22 | "-Werror", | ||
23 | "-Wno-user-defined-warnings", | ||
24 | ], | ||
25 | cppflags: [ | ||
26 | "-Weverything", | ||
27 | "-Wunused", | ||
28 | "-Wunreachable-code", | ||
29 | |||
30 | // The static constructors and destructors in this library have not been noted to | ||
31 | // introduce significant overheads | ||
32 | "-Wno-exit-time-destructors", | ||
33 | "-Wno-global-constructors", | ||
34 | |||
35 | // We only care about compiling as C++14 | ||
36 | "-Wno-c++98-compat-pedantic", | ||
37 | |||
38 | // android/sensors.h uses nested anonymous unions and anonymous structs | ||
39 | "-Wno-nested-anon-types", | ||
40 | "-Wno-gnu-anonymous-struct", | ||
41 | |||
42 | // Don't warn about struct padding | ||
43 | "-Wno-padded", | ||
44 | |||
45 | // hwcomposer2.h features switch covering all cases. | ||
46 | "-Wno-covered-switch-default", | ||
47 | |||
48 | // hwcomposer.h features zero size array. | ||
49 | "-Wno-zero-length-array", | ||
50 | |||
51 | // Disabling warning specific to hwc2on1adapter code | ||
52 | "-Wno-double-promotion", | ||
53 | "-Wno-sign-conversion", | ||
54 | "-Wno-switch-enum", | ||
55 | "-Wno-float-equal", | ||
56 | "-Wno-shorten-64-to-32", | ||
57 | "-Wno-sign-compare", | ||
58 | "-Wno-missing-prototypes", | ||
59 | ], | ||
60 | |||
61 | srcs: [ | ||
62 | "HWC2On1Adapter.cpp", | ||
63 | "MiniFence.cpp", | ||
64 | ], | ||
65 | |||
66 | shared_libs: [ | ||
67 | "libutils", | ||
68 | "libcutils", | ||
69 | "liblog", | ||
70 | "libhardware", | ||
71 | ], | ||
72 | |||
73 | export_include_dirs: ["include"], | ||
74 | |||
75 | export_shared_lib_headers: ["libutils"], | ||
76 | } | ||
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/CleanSpec.mk b/graphics/composer/2.1/utils/hwc2on1adapter/CleanSpec.mk new file mode 100644 index 00000000..7fc22161 --- /dev/null +++ b/graphics/composer/2.1/utils/hwc2on1adapter/CleanSpec.mk | |||
@@ -0,0 +1,52 @@ | |||
1 | # Copyright (C) 2017 The Android Open Source Project | ||
2 | # | ||
3 | # Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | # you may not use this file except in compliance with the License. | ||
5 | # You may obtain a copy of the License at | ||
6 | # | ||
7 | # http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | # | ||
9 | # Unless required by applicable law or agreed to in writing, software | ||
10 | # distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | # See the License for the specific language governing permissions and | ||
13 | # limitations under the License. | ||
14 | # | ||
15 | |||
16 | # If you don't need to do a full clean build but would like to touch | ||
17 | # a file or delete some intermediate files, add a clean step to the end | ||
18 | # of the list. These steps will only be run once, if they haven't been | ||
19 | # run before. | ||
20 | # | ||
21 | # E.g.: | ||
22 | # $(call add-clean-step, touch -c external/sqlite/sqlite3.h) | ||
23 | # $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) | ||
24 | # | ||
25 | # Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with | ||
26 | # files that are missing or have been moved. | ||
27 | # | ||
28 | # Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. | ||
29 | # Use $(OUT_DIR) to refer to the "out" directory. | ||
30 | # | ||
31 | # If you need to re-do something that's already mentioned, just copy | ||
32 | # the command and add it to the bottom of the list. E.g., if a change | ||
33 | # that you made last week required touching a file and a change you | ||
34 | # made today requires touching the same file, just copy the old | ||
35 | # touch step and add it to the end of the list. | ||
36 | # | ||
37 | # ************************************************ | ||
38 | # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST | ||
39 | # ************************************************ | ||
40 | |||
41 | # For example: | ||
42 | #$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) | ||
43 | #$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) | ||
44 | #$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) | ||
45 | #$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) | ||
46 | |||
47 | # ************************************************ | ||
48 | # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST | ||
49 | # ************************************************ | ||
50 | $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libhwc2on1adapter_intermediates) | ||
51 | $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/libhwc2on1adapter.so) | ||
52 | $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/libhwc2on1adapter.so) | ||
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp b/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp new file mode 100644 index 00000000..77f06bbb --- /dev/null +++ b/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp | |||
@@ -0,0 +1,2637 @@ | |||
1 | /* | ||
2 | * Copyright 2015 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include "hwc2on1adapter/HWC2On1Adapter.h" | ||
18 | |||
19 | //#define LOG_NDEBUG 0 | ||
20 | |||
21 | #undef LOG_TAG | ||
22 | #define LOG_TAG "HWC2On1Adapter" | ||
23 | #define ATRACE_TAG ATRACE_TAG_GRAPHICS | ||
24 | |||
25 | |||
26 | #include <inttypes.h> | ||
27 | |||
28 | #include <chrono> | ||
29 | #include <cstdlib> | ||
30 | #include <sstream> | ||
31 | |||
32 | #include <hardware/hwcomposer.h> | ||
33 | #include <log/log.h> | ||
34 | #include <utils/Trace.h> | ||
35 | |||
36 | using namespace std::chrono_literals; | ||
37 | |||
38 | static uint8_t getMinorVersion(struct hwc_composer_device_1* device) | ||
39 | { | ||
40 | auto version = device->common.version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK; | ||
41 | return (version >> 16) & 0xF; | ||
42 | } | ||
43 | |||
44 | template <typename PFN, typename T> | ||
45 | static hwc2_function_pointer_t asFP(T function) | ||
46 | { | ||
47 | static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer"); | ||
48 | return reinterpret_cast<hwc2_function_pointer_t>(function); | ||
49 | } | ||
50 | |||
51 | using namespace HWC2; | ||
52 | |||
53 | static constexpr Attribute ColorMode = static_cast<Attribute>(6); | ||
54 | |||
55 | namespace android { | ||
56 | |||
57 | class HWC2On1Adapter::Callbacks : public hwc_procs_t { | ||
58 | public: | ||
59 | explicit Callbacks(HWC2On1Adapter& adapter) : mAdapter(adapter) { | ||
60 | invalidate = &invalidateHook; | ||
61 | vsync = &vsyncHook; | ||
62 | hotplug = &hotplugHook; | ||
63 | } | ||
64 | |||
65 | static void invalidateHook(const hwc_procs_t* procs) { | ||
66 | auto callbacks = static_cast<const Callbacks*>(procs); | ||
67 | callbacks->mAdapter.hwc1Invalidate(); | ||
68 | } | ||
69 | |||
70 | static void vsyncHook(const hwc_procs_t* procs, int display, | ||
71 | int64_t timestamp) { | ||
72 | auto callbacks = static_cast<const Callbacks*>(procs); | ||
73 | callbacks->mAdapter.hwc1Vsync(display, timestamp); | ||
74 | } | ||
75 | |||
76 | static void hotplugHook(const hwc_procs_t* procs, int display, | ||
77 | int connected) { | ||
78 | auto callbacks = static_cast<const Callbacks*>(procs); | ||
79 | callbacks->mAdapter.hwc1Hotplug(display, connected); | ||
80 | } | ||
81 | |||
82 | private: | ||
83 | HWC2On1Adapter& mAdapter; | ||
84 | }; | ||
85 | |||
86 | static int closeHook(hw_device_t* /*device*/) | ||
87 | { | ||
88 | // Do nothing, since the real work is done in the class destructor, but we | ||
89 | // need to provide a valid function pointer for hwc2_close to call | ||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | HWC2On1Adapter::HWC2On1Adapter(hwc_composer_device_1_t* hwc1Device) | ||
94 | : mDumpString(), | ||
95 | mHwc1Device(hwc1Device), | ||
96 | mHwc1MinorVersion(getMinorVersion(hwc1Device)), | ||
97 | mHwc1SupportsVirtualDisplays(false), | ||
98 | mHwc1SupportsBackgroundColor(false), | ||
99 | mHwc1Callbacks(std::make_unique<Callbacks>(*this)), | ||
100 | mCapabilities(), | ||
101 | mLayers(), | ||
102 | mHwc1VirtualDisplay(), | ||
103 | mStateMutex(), | ||
104 | mCallbacks(), | ||
105 | mHasPendingInvalidate(false), | ||
106 | mPendingVsyncs(), | ||
107 | mPendingHotplugs(), | ||
108 | mDisplays(), | ||
109 | mHwc1DisplayMap() | ||
110 | { | ||
111 | common.close = closeHook; | ||
112 | getCapabilities = getCapabilitiesHook; | ||
113 | getFunction = getFunctionHook; | ||
114 | populateCapabilities(); | ||
115 | populatePrimary(); | ||
116 | mHwc1Device->registerProcs(mHwc1Device, | ||
117 | static_cast<const hwc_procs_t*>(mHwc1Callbacks.get())); | ||
118 | } | ||
119 | |||
120 | HWC2On1Adapter::~HWC2On1Adapter() { | ||
121 | hwc_close_1(mHwc1Device); | ||
122 | } | ||
123 | |||
124 | void HWC2On1Adapter::doGetCapabilities(uint32_t* outCount, | ||
125 | int32_t* outCapabilities) { | ||
126 | if (outCapabilities == nullptr) { | ||
127 | *outCount = mCapabilities.size(); | ||
128 | return; | ||
129 | } | ||
130 | |||
131 | auto capabilityIter = mCapabilities.cbegin(); | ||
132 | for (size_t written = 0; written < *outCount; ++written) { | ||
133 | if (capabilityIter == mCapabilities.cend()) { | ||
134 | return; | ||
135 | } | ||
136 | outCapabilities[written] = static_cast<int32_t>(*capabilityIter); | ||
137 | ++capabilityIter; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | hwc2_function_pointer_t HWC2On1Adapter::doGetFunction( | ||
142 | FunctionDescriptor descriptor) { | ||
143 | switch (descriptor) { | ||
144 | // Device functions | ||
145 | case FunctionDescriptor::CreateVirtualDisplay: | ||
146 | return asFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>( | ||
147 | createVirtualDisplayHook); | ||
148 | case FunctionDescriptor::DestroyVirtualDisplay: | ||
149 | return asFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>( | ||
150 | destroyVirtualDisplayHook); | ||
151 | case FunctionDescriptor::Dump: | ||
152 | return asFP<HWC2_PFN_DUMP>(dumpHook); | ||
153 | case FunctionDescriptor::GetMaxVirtualDisplayCount: | ||
154 | return asFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>( | ||
155 | getMaxVirtualDisplayCountHook); | ||
156 | case FunctionDescriptor::RegisterCallback: | ||
157 | return asFP<HWC2_PFN_REGISTER_CALLBACK>(registerCallbackHook); | ||
158 | |||
159 | // Display functions | ||
160 | case FunctionDescriptor::AcceptDisplayChanges: | ||
161 | return asFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>( | ||
162 | displayHook<decltype(&Display::acceptChanges), | ||
163 | &Display::acceptChanges>); | ||
164 | case FunctionDescriptor::CreateLayer: | ||
165 | return asFP<HWC2_PFN_CREATE_LAYER>( | ||
166 | displayHook<decltype(&Display::createLayer), | ||
167 | &Display::createLayer, hwc2_layer_t*>); | ||
168 | case FunctionDescriptor::DestroyLayer: | ||
169 | return asFP<HWC2_PFN_DESTROY_LAYER>( | ||
170 | displayHook<decltype(&Display::destroyLayer), | ||
171 | &Display::destroyLayer, hwc2_layer_t>); | ||
172 | case FunctionDescriptor::GetActiveConfig: | ||
173 | return asFP<HWC2_PFN_GET_ACTIVE_CONFIG>( | ||
174 | displayHook<decltype(&Display::getActiveConfig), | ||
175 | &Display::getActiveConfig, hwc2_config_t*>); | ||
176 | case FunctionDescriptor::GetChangedCompositionTypes: | ||
177 | return asFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>( | ||
178 | displayHook<decltype(&Display::getChangedCompositionTypes), | ||
179 | &Display::getChangedCompositionTypes, uint32_t*, | ||
180 | hwc2_layer_t*, int32_t*>); | ||
181 | case FunctionDescriptor::GetColorModes: | ||
182 | return asFP<HWC2_PFN_GET_COLOR_MODES>( | ||
183 | displayHook<decltype(&Display::getColorModes), | ||
184 | &Display::getColorModes, uint32_t*, int32_t*>); | ||
185 | case FunctionDescriptor::GetDisplayAttribute: | ||
186 | return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>( | ||
187 | getDisplayAttributeHook); | ||
188 | case FunctionDescriptor::GetDisplayConfigs: | ||
189 | return asFP<HWC2_PFN_GET_DISPLAY_CONFIGS>( | ||
190 | displayHook<decltype(&Display::getConfigs), | ||
191 | &Display::getConfigs, uint32_t*, hwc2_config_t*>); | ||
192 | case FunctionDescriptor::GetDisplayName: | ||
193 | return asFP<HWC2_PFN_GET_DISPLAY_NAME>( | ||
194 | displayHook<decltype(&Display::getName), | ||
195 | &Display::getName, uint32_t*, char*>); | ||
196 | case FunctionDescriptor::GetDisplayRequests: | ||
197 | return asFP<HWC2_PFN_GET_DISPLAY_REQUESTS>( | ||
198 | displayHook<decltype(&Display::getRequests), | ||
199 | &Display::getRequests, int32_t*, uint32_t*, hwc2_layer_t*, | ||
200 | int32_t*>); | ||
201 | case FunctionDescriptor::GetDisplayType: | ||
202 | return asFP<HWC2_PFN_GET_DISPLAY_TYPE>( | ||
203 | displayHook<decltype(&Display::getType), | ||
204 | &Display::getType, int32_t*>); | ||
205 | case FunctionDescriptor::GetDozeSupport: | ||
206 | return asFP<HWC2_PFN_GET_DOZE_SUPPORT>( | ||
207 | displayHook<decltype(&Display::getDozeSupport), | ||
208 | &Display::getDozeSupport, int32_t*>); | ||
209 | case FunctionDescriptor::GetHdrCapabilities: | ||
210 | return asFP<HWC2_PFN_GET_HDR_CAPABILITIES>( | ||
211 | displayHook<decltype(&Display::getHdrCapabilities), | ||
212 | &Display::getHdrCapabilities, uint32_t*, int32_t*, float*, | ||
213 | float*, float*>); | ||
214 | case FunctionDescriptor::GetReleaseFences: | ||
215 | return asFP<HWC2_PFN_GET_RELEASE_FENCES>( | ||
216 | displayHook<decltype(&Display::getReleaseFences), | ||
217 | &Display::getReleaseFences, uint32_t*, hwc2_layer_t*, | ||
218 | int32_t*>); | ||
219 | case FunctionDescriptor::PresentDisplay: | ||
220 | return asFP<HWC2_PFN_PRESENT_DISPLAY>( | ||
221 | displayHook<decltype(&Display::present), | ||
222 | &Display::present, int32_t*>); | ||
223 | case FunctionDescriptor::SetActiveConfig: | ||
224 | return asFP<HWC2_PFN_SET_ACTIVE_CONFIG>( | ||
225 | displayHook<decltype(&Display::setActiveConfig), | ||
226 | &Display::setActiveConfig, hwc2_config_t>); | ||
227 | case FunctionDescriptor::SetClientTarget: | ||
228 | return asFP<HWC2_PFN_SET_CLIENT_TARGET>( | ||
229 | displayHook<decltype(&Display::setClientTarget), | ||
230 | &Display::setClientTarget, buffer_handle_t, int32_t, | ||
231 | int32_t, hwc_region_t>); | ||
232 | case FunctionDescriptor::SetColorMode: | ||
233 | return asFP<HWC2_PFN_SET_COLOR_MODE>(setColorModeHook); | ||
234 | case FunctionDescriptor::SetColorTransform: | ||
235 | return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook); | ||
236 | case FunctionDescriptor::SetOutputBuffer: | ||
237 | return asFP<HWC2_PFN_SET_OUTPUT_BUFFER>( | ||
238 | displayHook<decltype(&Display::setOutputBuffer), | ||
239 | &Display::setOutputBuffer, buffer_handle_t, int32_t>); | ||
240 | case FunctionDescriptor::SetPowerMode: | ||
241 | return asFP<HWC2_PFN_SET_POWER_MODE>(setPowerModeHook); | ||
242 | case FunctionDescriptor::SetVsyncEnabled: | ||
243 | return asFP<HWC2_PFN_SET_VSYNC_ENABLED>(setVsyncEnabledHook); | ||
244 | case FunctionDescriptor::ValidateDisplay: | ||
245 | return asFP<HWC2_PFN_VALIDATE_DISPLAY>( | ||
246 | displayHook<decltype(&Display::validate), | ||
247 | &Display::validate, uint32_t*, uint32_t*>); | ||
248 | case FunctionDescriptor::GetClientTargetSupport: | ||
249 | return asFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>( | ||
250 | displayHook<decltype(&Display::getClientTargetSupport), | ||
251 | &Display::getClientTargetSupport, uint32_t, uint32_t, | ||
252 | int32_t, int32_t>); | ||
253 | |||
254 | // Layer functions | ||
255 | case FunctionDescriptor::SetCursorPosition: | ||
256 | return asFP<HWC2_PFN_SET_CURSOR_POSITION>( | ||
257 | layerHook<decltype(&Layer::setCursorPosition), | ||
258 | &Layer::setCursorPosition, int32_t, int32_t>); | ||
259 | case FunctionDescriptor::SetLayerBuffer: | ||
260 | return asFP<HWC2_PFN_SET_LAYER_BUFFER>( | ||
261 | layerHook<decltype(&Layer::setBuffer), &Layer::setBuffer, | ||
262 | buffer_handle_t, int32_t>); | ||
263 | case FunctionDescriptor::SetLayerSurfaceDamage: | ||
264 | return asFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>( | ||
265 | layerHook<decltype(&Layer::setSurfaceDamage), | ||
266 | &Layer::setSurfaceDamage, hwc_region_t>); | ||
267 | |||
268 | // Layer state functions | ||
269 | case FunctionDescriptor::SetLayerBlendMode: | ||
270 | return asFP<HWC2_PFN_SET_LAYER_BLEND_MODE>( | ||
271 | setLayerBlendModeHook); | ||
272 | case FunctionDescriptor::SetLayerColor: | ||
273 | return asFP<HWC2_PFN_SET_LAYER_COLOR>( | ||
274 | layerHook<decltype(&Layer::setColor), &Layer::setColor, | ||
275 | hwc_color_t>); | ||
276 | case FunctionDescriptor::SetLayerCompositionType: | ||
277 | return asFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>( | ||
278 | setLayerCompositionTypeHook); | ||
279 | case FunctionDescriptor::SetLayerDataspace: | ||
280 | return asFP<HWC2_PFN_SET_LAYER_DATASPACE>(setLayerDataspaceHook); | ||
281 | case FunctionDescriptor::SetLayerDisplayFrame: | ||
282 | return asFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>( | ||
283 | layerHook<decltype(&Layer::setDisplayFrame), | ||
284 | &Layer::setDisplayFrame, hwc_rect_t>); | ||
285 | case FunctionDescriptor::SetLayerPlaneAlpha: | ||
286 | return asFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>( | ||
287 | layerHook<decltype(&Layer::setPlaneAlpha), | ||
288 | &Layer::setPlaneAlpha, float>); | ||
289 | case FunctionDescriptor::SetLayerSidebandStream: | ||
290 | return asFP<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>( | ||
291 | layerHook<decltype(&Layer::setSidebandStream), | ||
292 | &Layer::setSidebandStream, const native_handle_t*>); | ||
293 | case FunctionDescriptor::SetLayerSourceCrop: | ||
294 | return asFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>( | ||
295 | layerHook<decltype(&Layer::setSourceCrop), | ||
296 | &Layer::setSourceCrop, hwc_frect_t>); | ||
297 | case FunctionDescriptor::SetLayerTransform: | ||
298 | return asFP<HWC2_PFN_SET_LAYER_TRANSFORM>(setLayerTransformHook); | ||
299 | case FunctionDescriptor::SetLayerVisibleRegion: | ||
300 | return asFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>( | ||
301 | layerHook<decltype(&Layer::setVisibleRegion), | ||
302 | &Layer::setVisibleRegion, hwc_region_t>); | ||
303 | case FunctionDescriptor::SetLayerZOrder: | ||
304 | return asFP<HWC2_PFN_SET_LAYER_Z_ORDER>(setLayerZOrderHook); | ||
305 | |||
306 | default: | ||
307 | ALOGE("doGetFunction: Unknown function descriptor: %d (%s)", | ||
308 | static_cast<int32_t>(descriptor), | ||
309 | to_string(descriptor).c_str()); | ||
310 | return nullptr; | ||
311 | } | ||
312 | } | ||
313 | |||
314 | // Device functions | ||
315 | |||
316 | Error HWC2On1Adapter::createVirtualDisplay(uint32_t width, | ||
317 | uint32_t height, hwc2_display_t* outDisplay) { | ||
318 | std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); | ||
319 | |||
320 | if (mHwc1VirtualDisplay) { | ||
321 | // We have already allocated our only HWC1 virtual display | ||
322 | ALOGE("createVirtualDisplay: HWC1 virtual display already allocated"); | ||
323 | return Error::NoResources; | ||
324 | } | ||
325 | |||
326 | mHwc1VirtualDisplay = std::make_shared<HWC2On1Adapter::Display>(*this, | ||
327 | HWC2::DisplayType::Virtual); | ||
328 | mHwc1VirtualDisplay->populateConfigs(width, height); | ||
329 | const auto displayId = mHwc1VirtualDisplay->getId(); | ||
330 | mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL] = displayId; | ||
331 | mHwc1VirtualDisplay->setHwc1Id(HWC_DISPLAY_VIRTUAL); | ||
332 | mDisplays.emplace(displayId, mHwc1VirtualDisplay); | ||
333 | *outDisplay = displayId; | ||
334 | |||
335 | return Error::None; | ||
336 | } | ||
337 | |||
338 | Error HWC2On1Adapter::destroyVirtualDisplay(hwc2_display_t displayId) { | ||
339 | std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); | ||
340 | |||
341 | if (!mHwc1VirtualDisplay || (mHwc1VirtualDisplay->getId() != displayId)) { | ||
342 | return Error::BadDisplay; | ||
343 | } | ||
344 | |||
345 | mHwc1VirtualDisplay.reset(); | ||
346 | mHwc1DisplayMap.erase(HWC_DISPLAY_VIRTUAL); | ||
347 | mDisplays.erase(displayId); | ||
348 | |||
349 | return Error::None; | ||
350 | } | ||
351 | |||
352 | void HWC2On1Adapter::dump(uint32_t* outSize, char* outBuffer) { | ||
353 | if (outBuffer != nullptr) { | ||
354 | auto copiedBytes = mDumpString.copy(outBuffer, *outSize); | ||
355 | *outSize = static_cast<uint32_t>(copiedBytes); | ||
356 | return; | ||
357 | } | ||
358 | |||
359 | std::stringstream output; | ||
360 | |||
361 | output << "-- HWC2On1Adapter --\n"; | ||
362 | |||
363 | output << "Adapting to a HWC 1." << static_cast<int>(mHwc1MinorVersion) << | ||
364 | " device\n"; | ||
365 | |||
366 | // Attempt to acquire the lock for 1 second, but proceed without the lock | ||
367 | // after that, so we can still get some information if we're deadlocked | ||
368 | std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex, | ||
369 | std::defer_lock); | ||
370 | lock.try_lock_for(1s); | ||
371 | |||
372 | if (mCapabilities.empty()) { | ||
373 | output << "Capabilities: None\n"; | ||
374 | } else { | ||
375 | output << "Capabilities:\n"; | ||
376 | for (auto capability : mCapabilities) { | ||
377 | output << " " << to_string(capability) << '\n'; | ||
378 | } | ||
379 | } | ||
380 | |||
381 | output << "Displays:\n"; | ||
382 | for (const auto& element : mDisplays) { | ||
383 | const auto& display = element.second; | ||
384 | output << display->dump(); | ||
385 | } | ||
386 | output << '\n'; | ||
387 | |||
388 | // Release the lock before calling into HWC1, and since we no longer require | ||
389 | // mutual exclusion to access mCapabilities or mDisplays | ||
390 | lock.unlock(); | ||
391 | |||
392 | if (mHwc1Device->dump) { | ||
393 | output << "HWC1 dump:\n"; | ||
394 | std::vector<char> hwc1Dump(4096); | ||
395 | // Call with size - 1 to preserve a null character at the end | ||
396 | mHwc1Device->dump(mHwc1Device, hwc1Dump.data(), | ||
397 | static_cast<int>(hwc1Dump.size() - 1)); | ||
398 | output << hwc1Dump.data(); | ||
399 | } | ||
400 | |||
401 | mDumpString = output.str(); | ||
402 | *outSize = static_cast<uint32_t>(mDumpString.size()); | ||
403 | } | ||
404 | |||
405 | uint32_t HWC2On1Adapter::getMaxVirtualDisplayCount() { | ||
406 | return mHwc1SupportsVirtualDisplays ? 1 : 0; | ||
407 | } | ||
408 | |||
409 | static bool isValid(Callback descriptor) { | ||
410 | switch (descriptor) { | ||
411 | case Callback::Hotplug: // Fall-through | ||
412 | case Callback::Refresh: // Fall-through | ||
413 | case Callback::Vsync: return true; | ||
414 | default: return false; | ||
415 | } | ||
416 | } | ||
417 | |||
418 | Error HWC2On1Adapter::registerCallback(Callback descriptor, | ||
419 | hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) { | ||
420 | if (!isValid(descriptor)) { | ||
421 | return Error::BadParameter; | ||
422 | } | ||
423 | |||
424 | ALOGV("registerCallback(%s, %p, %p)", to_string(descriptor).c_str(), | ||
425 | callbackData, pointer); | ||
426 | |||
427 | std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); | ||
428 | |||
429 | if (pointer != nullptr) { | ||
430 | mCallbacks[descriptor] = {callbackData, pointer}; | ||
431 | } else { | ||
432 | ALOGI("unregisterCallback(%s)", to_string(descriptor).c_str()); | ||
433 | mCallbacks.erase(descriptor); | ||
434 | return Error::None; | ||
435 | } | ||
436 | |||
437 | bool hasPendingInvalidate = false; | ||
438 | std::vector<hwc2_display_t> displayIds; | ||
439 | std::vector<std::pair<hwc2_display_t, int64_t>> pendingVsyncs; | ||
440 | std::vector<std::pair<hwc2_display_t, int>> pendingHotplugs; | ||
441 | |||
442 | if (descriptor == Callback::Refresh) { | ||
443 | hasPendingInvalidate = mHasPendingInvalidate; | ||
444 | if (hasPendingInvalidate) { | ||
445 | for (auto& displayPair : mDisplays) { | ||
446 | displayIds.emplace_back(displayPair.first); | ||
447 | } | ||
448 | } | ||
449 | mHasPendingInvalidate = false; | ||
450 | } else if (descriptor == Callback::Vsync) { | ||
451 | for (auto pending : mPendingVsyncs) { | ||
452 | auto hwc1DisplayId = pending.first; | ||
453 | if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) { | ||
454 | ALOGE("hwc1Vsync: Couldn't find display for HWC1 id %d", | ||
455 | hwc1DisplayId); | ||
456 | continue; | ||
457 | } | ||
458 | auto displayId = mHwc1DisplayMap[hwc1DisplayId]; | ||
459 | auto timestamp = pending.second; | ||
460 | pendingVsyncs.emplace_back(displayId, timestamp); | ||
461 | } | ||
462 | mPendingVsyncs.clear(); | ||
463 | } else if (descriptor == Callback::Hotplug) { | ||
464 | // Hotplug the primary display | ||
465 | pendingHotplugs.emplace_back(mHwc1DisplayMap[HWC_DISPLAY_PRIMARY], | ||
466 | static_cast<int32_t>(Connection::Connected)); | ||
467 | |||
468 | for (auto pending : mPendingHotplugs) { | ||
469 | auto hwc1DisplayId = pending.first; | ||
470 | if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) { | ||
471 | ALOGE("hwc1Hotplug: Couldn't find display for HWC1 id %d", | ||
472 | hwc1DisplayId); | ||
473 | continue; | ||
474 | } | ||
475 | auto displayId = mHwc1DisplayMap[hwc1DisplayId]; | ||
476 | auto connected = pending.second; | ||
477 | pendingHotplugs.emplace_back(displayId, connected); | ||
478 | } | ||
479 | } | ||
480 | |||
481 | // Call pending callbacks without the state lock held | ||
482 | lock.unlock(); | ||
483 | |||
484 | if (hasPendingInvalidate) { | ||
485 | auto refresh = reinterpret_cast<HWC2_PFN_REFRESH>(pointer); | ||
486 | for (auto displayId : displayIds) { | ||
487 | refresh(callbackData, displayId); | ||
488 | } | ||
489 | } | ||
490 | if (!pendingVsyncs.empty()) { | ||
491 | auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(pointer); | ||
492 | for (auto& pendingVsync : pendingVsyncs) { | ||
493 | vsync(callbackData, pendingVsync.first, pendingVsync.second); | ||
494 | } | ||
495 | } | ||
496 | if (!pendingHotplugs.empty()) { | ||
497 | auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer); | ||
498 | for (auto& pendingHotplug : pendingHotplugs) { | ||
499 | hotplug(callbackData, pendingHotplug.first, pendingHotplug.second); | ||
500 | } | ||
501 | } | ||
502 | return Error::None; | ||
503 | } | ||
504 | |||
505 | // Display functions | ||
506 | |||
507 | std::atomic<hwc2_display_t> HWC2On1Adapter::Display::sNextId(1); | ||
508 | |||
509 | HWC2On1Adapter::Display::Display(HWC2On1Adapter& device, HWC2::DisplayType type) | ||
510 | : mId(sNextId++), | ||
511 | mDevice(device), | ||
512 | mStateMutex(), | ||
513 | mHwc1RequestedContents(nullptr), | ||
514 | mRetireFence(), | ||
515 | mChanges(), | ||
516 | mHwc1Id(-1), | ||
517 | mConfigs(), | ||
518 | mActiveConfig(nullptr), | ||
519 | mActiveColorMode(static_cast<android_color_mode_t>(-1)), | ||
520 | mName(), | ||
521 | mType(type), | ||
522 | mPowerMode(PowerMode::Off), | ||
523 | mVsyncEnabled(Vsync::Invalid), | ||
524 | mClientTarget(), | ||
525 | mOutputBuffer(), | ||
526 | mHasColorTransform(false), | ||
527 | mLayers(), | ||
528 | mHwc1LayerMap(), | ||
529 | mNumAvailableRects(0), | ||
530 | mNextAvailableRect(nullptr), | ||
531 | mGeometryChanged(false) | ||
532 | {} | ||
533 | |||
534 | Error HWC2On1Adapter::Display::acceptChanges() { | ||
535 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
536 | |||
537 | if (!mChanges) { | ||
538 | ALOGV("[%" PRIu64 "] acceptChanges failed, not validated", mId); | ||
539 | return Error::NotValidated; | ||
540 | } | ||
541 | |||
542 | ALOGV("[%" PRIu64 "] acceptChanges", mId); | ||
543 | |||
544 | for (auto& change : mChanges->getTypeChanges()) { | ||
545 | auto layerId = change.first; | ||
546 | auto type = change.second; | ||
547 | if (mDevice.mLayers.count(layerId) == 0) { | ||
548 | // This should never happen but somehow does. | ||
549 | ALOGW("Cannot accept change for unknown layer (%" PRIu64 ")", | ||
550 | layerId); | ||
551 | continue; | ||
552 | } | ||
553 | auto layer = mDevice.mLayers[layerId]; | ||
554 | layer->setCompositionType(type); | ||
555 | } | ||
556 | |||
557 | mChanges->clearTypeChanges(); | ||
558 | |||
559 | return Error::None; | ||
560 | } | ||
561 | |||
562 | Error HWC2On1Adapter::Display::createLayer(hwc2_layer_t* outLayerId) { | ||
563 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
564 | |||
565 | auto layer = *mLayers.emplace(std::make_shared<Layer>(*this)); | ||
566 | mDevice.mLayers.emplace(std::make_pair(layer->getId(), layer)); | ||
567 | *outLayerId = layer->getId(); | ||
568 | ALOGV("[%" PRIu64 "] created layer %" PRIu64, mId, *outLayerId); | ||
569 | markGeometryChanged(); | ||
570 | return Error::None; | ||
571 | } | ||
572 | |||
573 | Error HWC2On1Adapter::Display::destroyLayer(hwc2_layer_t layerId) { | ||
574 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
575 | |||
576 | const auto mapLayer = mDevice.mLayers.find(layerId); | ||
577 | if (mapLayer == mDevice.mLayers.end()) { | ||
578 | ALOGV("[%" PRIu64 "] destroyLayer(%" PRIu64 ") failed: no such layer", | ||
579 | mId, layerId); | ||
580 | return Error::BadLayer; | ||
581 | } | ||
582 | const auto layer = mapLayer->second; | ||
583 | mDevice.mLayers.erase(mapLayer); | ||
584 | const auto zRange = mLayers.equal_range(layer); | ||
585 | for (auto current = zRange.first; current != zRange.second; ++current) { | ||
586 | if (**current == *layer) { | ||
587 | current = mLayers.erase(current); | ||
588 | break; | ||
589 | } | ||
590 | } | ||
591 | ALOGV("[%" PRIu64 "] destroyed layer %" PRIu64, mId, layerId); | ||
592 | markGeometryChanged(); | ||
593 | return Error::None; | ||
594 | } | ||
595 | |||
596 | Error HWC2On1Adapter::Display::getActiveConfig(hwc2_config_t* outConfig) { | ||
597 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
598 | |||
599 | if (!mActiveConfig) { | ||
600 | ALOGV("[%" PRIu64 "] getActiveConfig --> %s", mId, | ||
601 | to_string(Error::BadConfig).c_str()); | ||
602 | return Error::BadConfig; | ||
603 | } | ||
604 | auto configId = mActiveConfig->getId(); | ||
605 | ALOGV("[%" PRIu64 "] getActiveConfig --> %u", mId, configId); | ||
606 | *outConfig = configId; | ||
607 | return Error::None; | ||
608 | } | ||
609 | |||
610 | Error HWC2On1Adapter::Display::getAttribute(hwc2_config_t configId, | ||
611 | Attribute attribute, int32_t* outValue) { | ||
612 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
613 | |||
614 | if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) { | ||
615 | ALOGV("[%" PRIu64 "] getAttribute failed: bad config (%u)", mId, | ||
616 | configId); | ||
617 | return Error::BadConfig; | ||
618 | } | ||
619 | *outValue = mConfigs[configId]->getAttribute(attribute); | ||
620 | ALOGV("[%" PRIu64 "] getAttribute(%u, %s) --> %d", mId, configId, | ||
621 | to_string(attribute).c_str(), *outValue); | ||
622 | return Error::None; | ||
623 | } | ||
624 | |||
625 | Error HWC2On1Adapter::Display::getChangedCompositionTypes( | ||
626 | uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes) { | ||
627 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
628 | |||
629 | if (!mChanges) { | ||
630 | ALOGE("[%" PRIu64 "] getChangedCompositionTypes failed: not validated", | ||
631 | mId); | ||
632 | return Error::NotValidated; | ||
633 | } | ||
634 | |||
635 | if ((outLayers == nullptr) || (outTypes == nullptr)) { | ||
636 | *outNumElements = mChanges->getTypeChanges().size(); | ||
637 | return Error::None; | ||
638 | } | ||
639 | |||
640 | uint32_t numWritten = 0; | ||
641 | for (const auto& element : mChanges->getTypeChanges()) { | ||
642 | if (numWritten == *outNumElements) { | ||
643 | break; | ||
644 | } | ||
645 | auto layerId = element.first; | ||
646 | auto intType = static_cast<int32_t>(element.second); | ||
647 | ALOGV("Adding %" PRIu64 " %s", layerId, | ||
648 | to_string(element.second).c_str()); | ||
649 | outLayers[numWritten] = layerId; | ||
650 | outTypes[numWritten] = intType; | ||
651 | ++numWritten; | ||
652 | } | ||
653 | *outNumElements = numWritten; | ||
654 | |||
655 | return Error::None; | ||
656 | } | ||
657 | |||
658 | Error HWC2On1Adapter::Display::getColorModes(uint32_t* outNumModes, | ||
659 | int32_t* outModes) { | ||
660 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
661 | |||
662 | if (!outModes) { | ||
663 | *outNumModes = mColorModes.size(); | ||
664 | return Error::None; | ||
665 | } | ||
666 | uint32_t numModes = std::min(*outNumModes, | ||
667 | static_cast<uint32_t>(mColorModes.size())); | ||
668 | std::copy_n(mColorModes.cbegin(), numModes, outModes); | ||
669 | *outNumModes = numModes; | ||
670 | return Error::None; | ||
671 | } | ||
672 | |||
673 | Error HWC2On1Adapter::Display::getConfigs(uint32_t* outNumConfigs, | ||
674 | hwc2_config_t* outConfigs) { | ||
675 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
676 | |||
677 | if (!outConfigs) { | ||
678 | *outNumConfigs = mConfigs.size(); | ||
679 | return Error::None; | ||
680 | } | ||
681 | uint32_t numWritten = 0; | ||
682 | for (const auto& config : mConfigs) { | ||
683 | if (numWritten == *outNumConfigs) { | ||
684 | break; | ||
685 | } | ||
686 | outConfigs[numWritten] = config->getId(); | ||
687 | ++numWritten; | ||
688 | } | ||
689 | *outNumConfigs = numWritten; | ||
690 | return Error::None; | ||
691 | } | ||
692 | |||
693 | Error HWC2On1Adapter::Display::getDozeSupport(int32_t* outSupport) { | ||
694 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
695 | |||
696 | if (mDevice.mHwc1MinorVersion < 4 || mHwc1Id != 0) { | ||
697 | *outSupport = 0; | ||
698 | } else { | ||
699 | *outSupport = 1; | ||
700 | } | ||
701 | return Error::None; | ||
702 | } | ||
703 | |||
704 | Error HWC2On1Adapter::Display::getHdrCapabilities(uint32_t* outNumTypes, | ||
705 | int32_t* /*outTypes*/, float* /*outMaxLuminance*/, | ||
706 | float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/) { | ||
707 | // This isn't supported on HWC1, so per the HWC2 header, return numTypes = 0 | ||
708 | *outNumTypes = 0; | ||
709 | return Error::None; | ||
710 | } | ||
711 | |||
712 | Error HWC2On1Adapter::Display::getName(uint32_t* outSize, char* outName) { | ||
713 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
714 | |||
715 | if (!outName) { | ||
716 | *outSize = mName.size(); | ||
717 | return Error::None; | ||
718 | } | ||
719 | auto numCopied = mName.copy(outName, *outSize); | ||
720 | *outSize = numCopied; | ||
721 | return Error::None; | ||
722 | } | ||
723 | |||
724 | Error HWC2On1Adapter::Display::getReleaseFences(uint32_t* outNumElements, | ||
725 | hwc2_layer_t* outLayers, int32_t* outFences) { | ||
726 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
727 | |||
728 | uint32_t numWritten = 0; | ||
729 | bool outputsNonNull = (outLayers != nullptr) && (outFences != nullptr); | ||
730 | for (const auto& layer : mLayers) { | ||
731 | if (outputsNonNull && (numWritten == *outNumElements)) { | ||
732 | break; | ||
733 | } | ||
734 | |||
735 | auto releaseFence = layer->getReleaseFence(); | ||
736 | if (releaseFence != MiniFence::NO_FENCE) { | ||
737 | if (outputsNonNull) { | ||
738 | outLayers[numWritten] = layer->getId(); | ||
739 | outFences[numWritten] = releaseFence->dup(); | ||
740 | } | ||
741 | ++numWritten; | ||
742 | } | ||
743 | } | ||
744 | *outNumElements = numWritten; | ||
745 | |||
746 | return Error::None; | ||
747 | } | ||
748 | |||
749 | Error HWC2On1Adapter::Display::getRequests(int32_t* outDisplayRequests, | ||
750 | uint32_t* outNumElements, hwc2_layer_t* outLayers, | ||
751 | int32_t* outLayerRequests) { | ||
752 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
753 | |||
754 | if (!mChanges) { | ||
755 | return Error::NotValidated; | ||
756 | } | ||
757 | |||
758 | if (outLayers == nullptr || outLayerRequests == nullptr) { | ||
759 | *outNumElements = mChanges->getNumLayerRequests(); | ||
760 | return Error::None; | ||
761 | } | ||
762 | |||
763 | // Display requests (HWC2::DisplayRequest) are not supported by hwc1: | ||
764 | // A hwc1 has always zero requests for the client. | ||
765 | *outDisplayRequests = 0; | ||
766 | |||
767 | uint32_t numWritten = 0; | ||
768 | for (const auto& request : mChanges->getLayerRequests()) { | ||
769 | if (numWritten == *outNumElements) { | ||
770 | break; | ||
771 | } | ||
772 | outLayers[numWritten] = request.first; | ||
773 | outLayerRequests[numWritten] = static_cast<int32_t>(request.second); | ||
774 | ++numWritten; | ||
775 | } | ||
776 | |||
777 | return Error::None; | ||
778 | } | ||
779 | |||
780 | Error HWC2On1Adapter::Display::getType(int32_t* outType) { | ||
781 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
782 | |||
783 | *outType = static_cast<int32_t>(mType); | ||
784 | return Error::None; | ||
785 | } | ||
786 | |||
787 | Error HWC2On1Adapter::Display::present(int32_t* outRetireFence) { | ||
788 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
789 | |||
790 | if (mChanges) { | ||
791 | Error error = mDevice.setAllDisplays(); | ||
792 | if (error != Error::None) { | ||
793 | ALOGE("[%" PRIu64 "] present: setAllDisplaysFailed (%s)", mId, | ||
794 | to_string(error).c_str()); | ||
795 | return error; | ||
796 | } | ||
797 | } | ||
798 | |||
799 | *outRetireFence = mRetireFence.get()->dup(); | ||
800 | ALOGV("[%" PRIu64 "] present returning retire fence %d", mId, | ||
801 | *outRetireFence); | ||
802 | |||
803 | return Error::None; | ||
804 | } | ||
805 | |||
806 | Error HWC2On1Adapter::Display::setActiveConfig(hwc2_config_t configId) { | ||
807 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
808 | |||
809 | auto config = getConfig(configId); | ||
810 | if (!config) { | ||
811 | return Error::BadConfig; | ||
812 | } | ||
813 | if (config == mActiveConfig) { | ||
814 | return Error::None; | ||
815 | } | ||
816 | |||
817 | if (mDevice.mHwc1MinorVersion >= 4) { | ||
818 | uint32_t hwc1Id = 0; | ||
819 | auto error = config->getHwc1IdForColorMode(mActiveColorMode, &hwc1Id); | ||
820 | if (error != Error::None) { | ||
821 | return error; | ||
822 | } | ||
823 | |||
824 | int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, | ||
825 | mHwc1Id, static_cast<int>(hwc1Id)); | ||
826 | if (intError != 0) { | ||
827 | ALOGE("setActiveConfig: Failed to set active config on HWC1 (%d)", | ||
828 | intError); | ||
829 | return Error::BadConfig; | ||
830 | } | ||
831 | mActiveConfig = config; | ||
832 | } | ||
833 | |||
834 | return Error::None; | ||
835 | } | ||
836 | |||
837 | Error HWC2On1Adapter::Display::setClientTarget(buffer_handle_t target, | ||
838 | int32_t acquireFence, int32_t /*dataspace*/, hwc_region_t /*damage*/) { | ||
839 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
840 | |||
841 | ALOGV("[%" PRIu64 "] setClientTarget(%p, %d)", mId, target, acquireFence); | ||
842 | mClientTarget.setBuffer(target); | ||
843 | mClientTarget.setFence(acquireFence); | ||
844 | // dataspace and damage can't be used by HWC1, so ignore them | ||
845 | return Error::None; | ||
846 | } | ||
847 | |||
848 | Error HWC2On1Adapter::Display::setColorMode(android_color_mode_t mode) { | ||
849 | std::unique_lock<std::recursive_mutex> lock (mStateMutex); | ||
850 | |||
851 | ALOGV("[%" PRIu64 "] setColorMode(%d)", mId, mode); | ||
852 | |||
853 | if (mode == mActiveColorMode) { | ||
854 | return Error::None; | ||
855 | } | ||
856 | if (mColorModes.count(mode) == 0) { | ||
857 | ALOGE("[%" PRIu64 "] Mode %d not found in mColorModes", mId, mode); | ||
858 | return Error::Unsupported; | ||
859 | } | ||
860 | |||
861 | uint32_t hwc1Config = 0; | ||
862 | auto error = mActiveConfig->getHwc1IdForColorMode(mode, &hwc1Config); | ||
863 | if (error != Error::None) { | ||
864 | return error; | ||
865 | } | ||
866 | |||
867 | ALOGV("[%" PRIu64 "] Setting HWC1 config %u", mId, hwc1Config); | ||
868 | int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, | ||
869 | mHwc1Id, hwc1Config); | ||
870 | if (intError != 0) { | ||
871 | ALOGE("[%" PRIu64 "] Failed to set HWC1 config (%d)", mId, intError); | ||
872 | return Error::Unsupported; | ||
873 | } | ||
874 | |||
875 | mActiveColorMode = mode; | ||
876 | return Error::None; | ||
877 | } | ||
878 | |||
879 | Error HWC2On1Adapter::Display::setColorTransform(android_color_transform_t hint) { | ||
880 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
881 | |||
882 | ALOGV("%" PRIu64 "] setColorTransform(%d)", mId, | ||
883 | static_cast<int32_t>(hint)); | ||
884 | mHasColorTransform = (hint != HAL_COLOR_TRANSFORM_IDENTITY); | ||
885 | return Error::None; | ||
886 | } | ||
887 | |||
888 | Error HWC2On1Adapter::Display::setOutputBuffer(buffer_handle_t buffer, | ||
889 | int32_t releaseFence) { | ||
890 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
891 | |||
892 | ALOGV("[%" PRIu64 "] setOutputBuffer(%p, %d)", mId, buffer, releaseFence); | ||
893 | mOutputBuffer.setBuffer(buffer); | ||
894 | mOutputBuffer.setFence(releaseFence); | ||
895 | return Error::None; | ||
896 | } | ||
897 | |||
898 | static bool isValid(PowerMode mode) { | ||
899 | switch (mode) { | ||
900 | case PowerMode::Off: // Fall-through | ||
901 | case PowerMode::DozeSuspend: // Fall-through | ||
902 | case PowerMode::Doze: // Fall-through | ||
903 | case PowerMode::On: return true; | ||
904 | } | ||
905 | } | ||
906 | |||
907 | static int getHwc1PowerMode(PowerMode mode) { | ||
908 | switch (mode) { | ||
909 | case PowerMode::Off: return HWC_POWER_MODE_OFF; | ||
910 | case PowerMode::DozeSuspend: return HWC_POWER_MODE_DOZE_SUSPEND; | ||
911 | case PowerMode::Doze: return HWC_POWER_MODE_DOZE; | ||
912 | case PowerMode::On: return HWC_POWER_MODE_NORMAL; | ||
913 | } | ||
914 | } | ||
915 | |||
916 | Error HWC2On1Adapter::Display::setPowerMode(PowerMode mode) { | ||
917 | if (!isValid(mode)) { | ||
918 | return Error::BadParameter; | ||
919 | } | ||
920 | if (mode == mPowerMode) { | ||
921 | return Error::None; | ||
922 | } | ||
923 | |||
924 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
925 | |||
926 | int error = 0; | ||
927 | if (mDevice.mHwc1MinorVersion < 4) { | ||
928 | error = mDevice.mHwc1Device->blank(mDevice.mHwc1Device, mHwc1Id, | ||
929 | mode == PowerMode::Off); | ||
930 | } else { | ||
931 | error = mDevice.mHwc1Device->setPowerMode(mDevice.mHwc1Device, | ||
932 | mHwc1Id, getHwc1PowerMode(mode)); | ||
933 | } | ||
934 | ALOGE_IF(error != 0, "setPowerMode: Failed to set power mode on HWC1 (%d)", | ||
935 | error); | ||
936 | |||
937 | ALOGV("[%" PRIu64 "] setPowerMode(%s)", mId, to_string(mode).c_str()); | ||
938 | mPowerMode = mode; | ||
939 | return Error::None; | ||
940 | } | ||
941 | |||
942 | static bool isValid(Vsync enable) { | ||
943 | switch (enable) { | ||
944 | case Vsync::Enable: // Fall-through | ||
945 | case Vsync::Disable: return true; | ||
946 | case Vsync::Invalid: return false; | ||
947 | } | ||
948 | } | ||
949 | |||
950 | Error HWC2On1Adapter::Display::setVsyncEnabled(Vsync enable) { | ||
951 | if (!isValid(enable)) { | ||
952 | return Error::BadParameter; | ||
953 | } | ||
954 | if (enable == mVsyncEnabled) { | ||
955 | return Error::None; | ||
956 | } | ||
957 | |||
958 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
959 | |||
960 | int error = mDevice.mHwc1Device->eventControl(mDevice.mHwc1Device, | ||
961 | mHwc1Id, HWC_EVENT_VSYNC, enable == Vsync::Enable); | ||
962 | ALOGE_IF(error != 0, "setVsyncEnabled: Failed to set vsync on HWC1 (%d)", | ||
963 | error); | ||
964 | |||
965 | mVsyncEnabled = enable; | ||
966 | return Error::None; | ||
967 | } | ||
968 | |||
969 | Error HWC2On1Adapter::Display::validate(uint32_t* outNumTypes, | ||
970 | uint32_t* outNumRequests) { | ||
971 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
972 | |||
973 | if (!mChanges) { | ||
974 | if (!mDevice.prepareAllDisplays()) { | ||
975 | return Error::BadDisplay; | ||
976 | } | ||
977 | } else { | ||
978 | ALOGE("Validate was called more than once!"); | ||
979 | } | ||
980 | |||
981 | *outNumTypes = mChanges->getNumTypes(); | ||
982 | *outNumRequests = mChanges->getNumLayerRequests(); | ||
983 | ALOGV("[%" PRIu64 "] validate --> %u types, %u requests", mId, *outNumTypes, | ||
984 | *outNumRequests); | ||
985 | for (auto request : mChanges->getTypeChanges()) { | ||
986 | ALOGV("Layer %" PRIu64 " --> %s", request.first, | ||
987 | to_string(request.second).c_str()); | ||
988 | } | ||
989 | return *outNumTypes > 0 ? Error::HasChanges : Error::None; | ||
990 | } | ||
991 | |||
992 | Error HWC2On1Adapter::Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z) { | ||
993 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
994 | |||
995 | const auto mapLayer = mDevice.mLayers.find(layerId); | ||
996 | if (mapLayer == mDevice.mLayers.end()) { | ||
997 | ALOGE("[%" PRIu64 "] updateLayerZ failed to find layer", mId); | ||
998 | return Error::BadLayer; | ||
999 | } | ||
1000 | |||
1001 | const auto layer = mapLayer->second; | ||
1002 | const auto zRange = mLayers.equal_range(layer); | ||
1003 | bool layerOnDisplay = false; | ||
1004 | for (auto current = zRange.first; current != zRange.second; ++current) { | ||
1005 | if (**current == *layer) { | ||
1006 | if ((*current)->getZ() == z) { | ||
1007 | // Don't change anything if the Z hasn't changed | ||
1008 | return Error::None; | ||
1009 | } | ||
1010 | current = mLayers.erase(current); | ||
1011 | layerOnDisplay = true; | ||
1012 | break; | ||
1013 | } | ||
1014 | } | ||
1015 | |||
1016 | if (!layerOnDisplay) { | ||
1017 | ALOGE("[%" PRIu64 "] updateLayerZ failed to find layer on display", | ||
1018 | mId); | ||
1019 | return Error::BadLayer; | ||
1020 | } | ||
1021 | |||
1022 | layer->setZ(z); | ||
1023 | mLayers.emplace(std::move(layer)); | ||
1024 | markGeometryChanged(); | ||
1025 | |||
1026 | return Error::None; | ||
1027 | } | ||
1028 | |||
1029 | Error HWC2On1Adapter::Display::getClientTargetSupport(uint32_t width, uint32_t height, | ||
1030 | int32_t format, int32_t dataspace){ | ||
1031 | if (mActiveConfig == nullptr) { | ||
1032 | return Error::Unsupported; | ||
1033 | } | ||
1034 | |||
1035 | if (width == mActiveConfig->getAttribute(Attribute::Width) && | ||
1036 | height == mActiveConfig->getAttribute(Attribute::Height) && | ||
1037 | format == HAL_PIXEL_FORMAT_RGBA_8888 && | ||
1038 | dataspace == HAL_DATASPACE_UNKNOWN) { | ||
1039 | return Error::None; | ||
1040 | } | ||
1041 | |||
1042 | return Error::Unsupported; | ||
1043 | } | ||
1044 | |||
1045 | static constexpr uint32_t ATTRIBUTES_WITH_COLOR[] = { | ||
1046 | HWC_DISPLAY_VSYNC_PERIOD, | ||
1047 | HWC_DISPLAY_WIDTH, | ||
1048 | HWC_DISPLAY_HEIGHT, | ||
1049 | HWC_DISPLAY_DPI_X, | ||
1050 | HWC_DISPLAY_DPI_Y, | ||
1051 | HWC_DISPLAY_COLOR_TRANSFORM, | ||
1052 | HWC_DISPLAY_NO_ATTRIBUTE, | ||
1053 | }; | ||
1054 | |||
1055 | static constexpr uint32_t ATTRIBUTES_WITHOUT_COLOR[] = { | ||
1056 | HWC_DISPLAY_VSYNC_PERIOD, | ||
1057 | HWC_DISPLAY_WIDTH, | ||
1058 | HWC_DISPLAY_HEIGHT, | ||
1059 | HWC_DISPLAY_DPI_X, | ||
1060 | HWC_DISPLAY_DPI_Y, | ||
1061 | HWC_DISPLAY_NO_ATTRIBUTE, | ||
1062 | }; | ||
1063 | |||
1064 | static constexpr size_t NUM_ATTRIBUTES_WITH_COLOR = | ||
1065 | sizeof(ATTRIBUTES_WITH_COLOR) / sizeof(uint32_t); | ||
1066 | static_assert(sizeof(ATTRIBUTES_WITH_COLOR) > sizeof(ATTRIBUTES_WITHOUT_COLOR), | ||
1067 | "Attribute tables have unexpected sizes"); | ||
1068 | |||
1069 | static constexpr uint32_t ATTRIBUTE_MAP_WITH_COLOR[] = { | ||
1070 | 6, // HWC_DISPLAY_NO_ATTRIBUTE = 0 | ||
1071 | 0, // HWC_DISPLAY_VSYNC_PERIOD = 1, | ||
1072 | 1, // HWC_DISPLAY_WIDTH = 2, | ||
1073 | 2, // HWC_DISPLAY_HEIGHT = 3, | ||
1074 | 3, // HWC_DISPLAY_DPI_X = 4, | ||
1075 | 4, // HWC_DISPLAY_DPI_Y = 5, | ||
1076 | 5, // HWC_DISPLAY_COLOR_TRANSFORM = 6, | ||
1077 | }; | ||
1078 | |||
1079 | static constexpr uint32_t ATTRIBUTE_MAP_WITHOUT_COLOR[] = { | ||
1080 | 5, // HWC_DISPLAY_NO_ATTRIBUTE = 0 | ||
1081 | 0, // HWC_DISPLAY_VSYNC_PERIOD = 1, | ||
1082 | 1, // HWC_DISPLAY_WIDTH = 2, | ||
1083 | 2, // HWC_DISPLAY_HEIGHT = 3, | ||
1084 | 3, // HWC_DISPLAY_DPI_X = 4, | ||
1085 | 4, // HWC_DISPLAY_DPI_Y = 5, | ||
1086 | }; | ||
1087 | |||
1088 | template <uint32_t attribute> | ||
1089 | static constexpr bool attributesMatch() | ||
1090 | { | ||
1091 | bool match = (attribute == | ||
1092 | ATTRIBUTES_WITH_COLOR[ATTRIBUTE_MAP_WITH_COLOR[attribute]]); | ||
1093 | if (attribute == HWC_DISPLAY_COLOR_TRANSFORM) { | ||
1094 | return match; | ||
1095 | } | ||
1096 | |||
1097 | return match && (attribute == | ||
1098 | ATTRIBUTES_WITHOUT_COLOR[ATTRIBUTE_MAP_WITHOUT_COLOR[attribute]]); | ||
1099 | } | ||
1100 | static_assert(attributesMatch<HWC_DISPLAY_VSYNC_PERIOD>(), | ||
1101 | "Tables out of sync"); | ||
1102 | static_assert(attributesMatch<HWC_DISPLAY_WIDTH>(), "Tables out of sync"); | ||
1103 | static_assert(attributesMatch<HWC_DISPLAY_HEIGHT>(), "Tables out of sync"); | ||
1104 | static_assert(attributesMatch<HWC_DISPLAY_DPI_X>(), "Tables out of sync"); | ||
1105 | static_assert(attributesMatch<HWC_DISPLAY_DPI_Y>(), "Tables out of sync"); | ||
1106 | static_assert(attributesMatch<HWC_DISPLAY_COLOR_TRANSFORM>(), | ||
1107 | "Tables out of sync"); | ||
1108 | |||
1109 | void HWC2On1Adapter::Display::populateConfigs() { | ||
1110 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
1111 | |||
1112 | ALOGV("[%" PRIu64 "] populateConfigs", mId); | ||
1113 | |||
1114 | if (mHwc1Id == -1) { | ||
1115 | ALOGE("populateConfigs: HWC1 ID not set"); | ||
1116 | return; | ||
1117 | } | ||
1118 | |||
1119 | const size_t MAX_NUM_CONFIGS = 128; | ||
1120 | uint32_t configs[MAX_NUM_CONFIGS] = {}; | ||
1121 | size_t numConfigs = MAX_NUM_CONFIGS; | ||
1122 | mDevice.mHwc1Device->getDisplayConfigs(mDevice.mHwc1Device, mHwc1Id, | ||
1123 | configs, &numConfigs); | ||
1124 | |||
1125 | for (size_t c = 0; c < numConfigs; ++c) { | ||
1126 | uint32_t hwc1ConfigId = configs[c]; | ||
1127 | auto newConfig = std::make_shared<Config>(*this); | ||
1128 | |||
1129 | int32_t values[NUM_ATTRIBUTES_WITH_COLOR] = {}; | ||
1130 | bool hasColor = true; | ||
1131 | auto result = mDevice.mHwc1Device->getDisplayAttributes( | ||
1132 | mDevice.mHwc1Device, mHwc1Id, hwc1ConfigId, | ||
1133 | ATTRIBUTES_WITH_COLOR, values); | ||
1134 | if (result != 0) { | ||
1135 | mDevice.mHwc1Device->getDisplayAttributes(mDevice.mHwc1Device, | ||
1136 | mHwc1Id, hwc1ConfigId, ATTRIBUTES_WITHOUT_COLOR, values); | ||
1137 | hasColor = false; | ||
1138 | } | ||
1139 | |||
1140 | auto attributeMap = hasColor ? | ||
1141 | ATTRIBUTE_MAP_WITH_COLOR : ATTRIBUTE_MAP_WITHOUT_COLOR; | ||
1142 | |||
1143 | newConfig->setAttribute(Attribute::VsyncPeriod, | ||
1144 | values[attributeMap[HWC_DISPLAY_VSYNC_PERIOD]]); | ||
1145 | newConfig->setAttribute(Attribute::Width, | ||
1146 | values[attributeMap[HWC_DISPLAY_WIDTH]]); | ||
1147 | newConfig->setAttribute(Attribute::Height, | ||
1148 | values[attributeMap[HWC_DISPLAY_HEIGHT]]); | ||
1149 | newConfig->setAttribute(Attribute::DpiX, | ||
1150 | values[attributeMap[HWC_DISPLAY_DPI_X]]); | ||
1151 | newConfig->setAttribute(Attribute::DpiY, | ||
1152 | values[attributeMap[HWC_DISPLAY_DPI_Y]]); | ||
1153 | if (hasColor) { | ||
1154 | // In HWC1, color modes are referred to as color transforms. To avoid confusion with | ||
1155 | // the HWC2 concept of color transforms, we internally refer to them as color modes for | ||
1156 | // both HWC1 and 2. | ||
1157 | newConfig->setAttribute(ColorMode, | ||
1158 | values[attributeMap[HWC_DISPLAY_COLOR_TRANSFORM]]); | ||
1159 | } | ||
1160 | |||
1161 | // We can only do this after attempting to read the color mode | ||
1162 | newConfig->setHwc1Id(hwc1ConfigId); | ||
1163 | |||
1164 | for (auto& existingConfig : mConfigs) { | ||
1165 | if (existingConfig->merge(*newConfig)) { | ||
1166 | ALOGV("Merged config %d with existing config %u: %s", | ||
1167 | hwc1ConfigId, existingConfig->getId(), | ||
1168 | existingConfig->toString().c_str()); | ||
1169 | newConfig.reset(); | ||
1170 | break; | ||
1171 | } | ||
1172 | } | ||
1173 | |||
1174 | // If it wasn't merged with any existing config, add it to the end | ||
1175 | if (newConfig) { | ||
1176 | newConfig->setId(static_cast<hwc2_config_t>(mConfigs.size())); | ||
1177 | ALOGV("Found new config %u: %s", newConfig->getId(), | ||
1178 | newConfig->toString().c_str()); | ||
1179 | mConfigs.emplace_back(std::move(newConfig)); | ||
1180 | } | ||
1181 | } | ||
1182 | |||
1183 | initializeActiveConfig(); | ||
1184 | populateColorModes(); | ||
1185 | } | ||
1186 | |||
1187 | void HWC2On1Adapter::Display::populateConfigs(uint32_t width, uint32_t height) { | ||
1188 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
1189 | |||
1190 | mConfigs.emplace_back(std::make_shared<Config>(*this)); | ||
1191 | auto& config = mConfigs[0]; | ||
1192 | |||
1193 | config->setAttribute(Attribute::Width, static_cast<int32_t>(width)); | ||
1194 | config->setAttribute(Attribute::Height, static_cast<int32_t>(height)); | ||
1195 | config->setHwc1Id(0); | ||
1196 | config->setId(0); | ||
1197 | mActiveConfig = config; | ||
1198 | } | ||
1199 | |||
1200 | bool HWC2On1Adapter::Display::prepare() { | ||
1201 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
1202 | |||
1203 | // Only prepare display contents for displays HWC1 knows about | ||
1204 | if (mHwc1Id == -1) { | ||
1205 | return true; | ||
1206 | } | ||
1207 | |||
1208 | // It doesn't make sense to prepare a display for which there is no active | ||
1209 | // config, so return early | ||
1210 | if (!mActiveConfig) { | ||
1211 | ALOGE("[%" PRIu64 "] Attempted to prepare, but no config active", mId); | ||
1212 | return false; | ||
1213 | } | ||
1214 | |||
1215 | allocateRequestedContents(); | ||
1216 | assignHwc1LayerIds(); | ||
1217 | |||
1218 | mHwc1RequestedContents->retireFenceFd = -1; | ||
1219 | mHwc1RequestedContents->flags = 0; | ||
1220 | if (mGeometryChanged) { | ||
1221 | mHwc1RequestedContents->flags |= HWC_GEOMETRY_CHANGED; | ||
1222 | } | ||
1223 | mHwc1RequestedContents->outbuf = mOutputBuffer.getBuffer(); | ||
1224 | mHwc1RequestedContents->outbufAcquireFenceFd = mOutputBuffer.getFence(); | ||
1225 | |||
1226 | // +1 is for framebuffer target layer. | ||
1227 | mHwc1RequestedContents->numHwLayers = mLayers.size() + 1; | ||
1228 | for (auto& layer : mLayers) { | ||
1229 | auto& hwc1Layer = mHwc1RequestedContents->hwLayers[layer->getHwc1Id()]; | ||
1230 | hwc1Layer.releaseFenceFd = -1; | ||
1231 | hwc1Layer.acquireFenceFd = -1; | ||
1232 | ALOGV("Applying states for layer %" PRIu64 " ", layer->getId()); | ||
1233 | layer->applyState(hwc1Layer); | ||
1234 | } | ||
1235 | |||
1236 | prepareFramebufferTarget(); | ||
1237 | |||
1238 | resetGeometryMarker(); | ||
1239 | |||
1240 | return true; | ||
1241 | } | ||
1242 | |||
1243 | void HWC2On1Adapter::Display::generateChanges() { | ||
1244 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
1245 | |||
1246 | mChanges.reset(new Changes); | ||
1247 | |||
1248 | size_t numLayers = mHwc1RequestedContents->numHwLayers; | ||
1249 | for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) { | ||
1250 | const auto& receivedLayer = mHwc1RequestedContents->hwLayers[hwc1Id]; | ||
1251 | if (mHwc1LayerMap.count(hwc1Id) == 0) { | ||
1252 | ALOGE_IF(receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET, | ||
1253 | "generateChanges: HWC1 layer %zd doesn't have a" | ||
1254 | " matching HWC2 layer, and isn't the framebuffer target", | ||
1255 | hwc1Id); | ||
1256 | continue; | ||
1257 | } | ||
1258 | |||
1259 | Layer& layer = *mHwc1LayerMap[hwc1Id]; | ||
1260 | updateTypeChanges(receivedLayer, layer); | ||
1261 | updateLayerRequests(receivedLayer, layer); | ||
1262 | } | ||
1263 | } | ||
1264 | |||
1265 | bool HWC2On1Adapter::Display::hasChanges() const { | ||
1266 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
1267 | return mChanges != nullptr; | ||
1268 | } | ||
1269 | |||
1270 | Error HWC2On1Adapter::Display::set(hwc_display_contents_1& hwcContents) { | ||
1271 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
1272 | |||
1273 | if (!mChanges || (mChanges->getNumTypes() > 0)) { | ||
1274 | ALOGE("[%" PRIu64 "] set failed: not validated", mId); | ||
1275 | return Error::NotValidated; | ||
1276 | } | ||
1277 | |||
1278 | // Set up the client/framebuffer target | ||
1279 | auto numLayers = hwcContents.numHwLayers; | ||
1280 | |||
1281 | // Close acquire fences on FRAMEBUFFER layers, since they will not be used | ||
1282 | // by HWC | ||
1283 | for (size_t l = 0; l < numLayers - 1; ++l) { | ||
1284 | auto& layer = hwcContents.hwLayers[l]; | ||
1285 | if (layer.compositionType == HWC_FRAMEBUFFER) { | ||
1286 | ALOGV("Closing fence %d for layer %zd", layer.acquireFenceFd, l); | ||
1287 | close(layer.acquireFenceFd); | ||
1288 | layer.acquireFenceFd = -1; | ||
1289 | } | ||
1290 | } | ||
1291 | |||
1292 | auto& clientTargetLayer = hwcContents.hwLayers[numLayers - 1]; | ||
1293 | if (clientTargetLayer.compositionType == HWC_FRAMEBUFFER_TARGET) { | ||
1294 | clientTargetLayer.handle = mClientTarget.getBuffer(); | ||
1295 | clientTargetLayer.acquireFenceFd = mClientTarget.getFence(); | ||
1296 | } else { | ||
1297 | ALOGE("[%" PRIu64 "] set: last HWC layer wasn't FRAMEBUFFER_TARGET", | ||
1298 | mId); | ||
1299 | } | ||
1300 | |||
1301 | mChanges.reset(); | ||
1302 | |||
1303 | return Error::None; | ||
1304 | } | ||
1305 | |||
1306 | void HWC2On1Adapter::Display::addRetireFence(int fenceFd) { | ||
1307 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
1308 | mRetireFence.add(fenceFd); | ||
1309 | } | ||
1310 | |||
1311 | void HWC2On1Adapter::Display::addReleaseFences( | ||
1312 | const hwc_display_contents_1_t& hwcContents) { | ||
1313 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
1314 | |||
1315 | size_t numLayers = hwcContents.numHwLayers; | ||
1316 | for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) { | ||
1317 | const auto& receivedLayer = hwcContents.hwLayers[hwc1Id]; | ||
1318 | if (mHwc1LayerMap.count(hwc1Id) == 0) { | ||
1319 | if (receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET) { | ||
1320 | ALOGE("addReleaseFences: HWC1 layer %zd doesn't have a" | ||
1321 | " matching HWC2 layer, and isn't the framebuffer" | ||
1322 | " target", hwc1Id); | ||
1323 | } | ||
1324 | // Close the framebuffer target release fence since we will use the | ||
1325 | // display retire fence instead | ||
1326 | if (receivedLayer.releaseFenceFd != -1) { | ||
1327 | close(receivedLayer.releaseFenceFd); | ||
1328 | } | ||
1329 | continue; | ||
1330 | } | ||
1331 | |||
1332 | Layer& layer = *mHwc1LayerMap[hwc1Id]; | ||
1333 | ALOGV("Adding release fence %d to layer %" PRIu64, | ||
1334 | receivedLayer.releaseFenceFd, layer.getId()); | ||
1335 | layer.addReleaseFence(receivedLayer.releaseFenceFd); | ||
1336 | } | ||
1337 | } | ||
1338 | |||
1339 | bool HWC2On1Adapter::Display::hasColorTransform() const { | ||
1340 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
1341 | return mHasColorTransform; | ||
1342 | } | ||
1343 | |||
1344 | static std::string hwc1CompositionString(int32_t type) { | ||
1345 | switch (type) { | ||
1346 | case HWC_FRAMEBUFFER: return "Framebuffer"; | ||
1347 | case HWC_OVERLAY: return "Overlay"; | ||
1348 | case HWC_BACKGROUND: return "Background"; | ||
1349 | case HWC_FRAMEBUFFER_TARGET: return "FramebufferTarget"; | ||
1350 | case HWC_SIDEBAND: return "Sideband"; | ||
1351 | case HWC_CURSOR_OVERLAY: return "CursorOverlay"; | ||
1352 | default: | ||
1353 | return std::string("Unknown (") + std::to_string(type) + ")"; | ||
1354 | } | ||
1355 | } | ||
1356 | |||
1357 | static std::string hwc1TransformString(int32_t transform) { | ||
1358 | switch (transform) { | ||
1359 | case 0: return "None"; | ||
1360 | case HWC_TRANSFORM_FLIP_H: return "FlipH"; | ||
1361 | case HWC_TRANSFORM_FLIP_V: return "FlipV"; | ||
1362 | case HWC_TRANSFORM_ROT_90: return "Rotate90"; | ||
1363 | case HWC_TRANSFORM_ROT_180: return "Rotate180"; | ||
1364 | case HWC_TRANSFORM_ROT_270: return "Rotate270"; | ||
1365 | case HWC_TRANSFORM_FLIP_H_ROT_90: return "FlipHRotate90"; | ||
1366 | case HWC_TRANSFORM_FLIP_V_ROT_90: return "FlipVRotate90"; | ||
1367 | default: | ||
1368 | return std::string("Unknown (") + std::to_string(transform) + ")"; | ||
1369 | } | ||
1370 | } | ||
1371 | |||
1372 | static std::string hwc1BlendModeString(int32_t mode) { | ||
1373 | switch (mode) { | ||
1374 | case HWC_BLENDING_NONE: return "None"; | ||
1375 | case HWC_BLENDING_PREMULT: return "Premultiplied"; | ||
1376 | case HWC_BLENDING_COVERAGE: return "Coverage"; | ||
1377 | default: | ||
1378 | return std::string("Unknown (") + std::to_string(mode) + ")"; | ||
1379 | } | ||
1380 | } | ||
1381 | |||
1382 | static std::string rectString(hwc_rect_t rect) { | ||
1383 | std::stringstream output; | ||
1384 | output << "[" << rect.left << ", " << rect.top << ", "; | ||
1385 | output << rect.right << ", " << rect.bottom << "]"; | ||
1386 | return output.str(); | ||
1387 | } | ||
1388 | |||
1389 | static std::string approximateFloatString(float f) { | ||
1390 | if (static_cast<int32_t>(f) == f) { | ||
1391 | return std::to_string(static_cast<int32_t>(f)); | ||
1392 | } | ||
1393 | int32_t truncated = static_cast<int32_t>(f * 10); | ||
1394 | bool approximate = (static_cast<float>(truncated) != f * 10); | ||
1395 | const size_t BUFFER_SIZE = 32; | ||
1396 | char buffer[BUFFER_SIZE] = {}; | ||
1397 | auto bytesWritten = snprintf(buffer, BUFFER_SIZE, | ||
1398 | "%s%.1f", approximate ? "~" : "", f); | ||
1399 | return std::string(buffer, bytesWritten); | ||
1400 | } | ||
1401 | |||
1402 | static std::string frectString(hwc_frect_t frect) { | ||
1403 | std::stringstream output; | ||
1404 | output << "[" << approximateFloatString(frect.left) << ", "; | ||
1405 | output << approximateFloatString(frect.top) << ", "; | ||
1406 | output << approximateFloatString(frect.right) << ", "; | ||
1407 | output << approximateFloatString(frect.bottom) << "]"; | ||
1408 | return output.str(); | ||
1409 | } | ||
1410 | |||
1411 | static std::string colorString(hwc_color_t color) { | ||
1412 | std::stringstream output; | ||
1413 | output << "RGBA ["; | ||
1414 | output << static_cast<int32_t>(color.r) << ", "; | ||
1415 | output << static_cast<int32_t>(color.g) << ", "; | ||
1416 | output << static_cast<int32_t>(color.b) << ", "; | ||
1417 | output << static_cast<int32_t>(color.a) << "]"; | ||
1418 | return output.str(); | ||
1419 | } | ||
1420 | |||
1421 | static std::string alphaString(float f) { | ||
1422 | const size_t BUFFER_SIZE = 8; | ||
1423 | char buffer[BUFFER_SIZE] = {}; | ||
1424 | auto bytesWritten = snprintf(buffer, BUFFER_SIZE, "%.3f", f); | ||
1425 | return std::string(buffer, bytesWritten); | ||
1426 | } | ||
1427 | |||
1428 | static std::string to_string(const hwc_layer_1_t& hwcLayer, | ||
1429 | int32_t hwc1MinorVersion) { | ||
1430 | const char* fill = " "; | ||
1431 | |||
1432 | std::stringstream output; | ||
1433 | |||
1434 | output << " Composition: " << | ||
1435 | hwc1CompositionString(hwcLayer.compositionType); | ||
1436 | |||
1437 | if (hwcLayer.compositionType == HWC_BACKGROUND) { | ||
1438 | output << " Color: " << colorString(hwcLayer.backgroundColor) << '\n'; | ||
1439 | } else if (hwcLayer.compositionType == HWC_SIDEBAND) { | ||
1440 | output << " Stream: " << hwcLayer.sidebandStream << '\n'; | ||
1441 | } else { | ||
1442 | output << " Buffer: " << hwcLayer.handle << "/" << | ||
1443 | hwcLayer.acquireFenceFd << '\n'; | ||
1444 | } | ||
1445 | |||
1446 | output << fill << "Display frame: " << rectString(hwcLayer.displayFrame) << | ||
1447 | '\n'; | ||
1448 | |||
1449 | output << fill << "Source crop: "; | ||
1450 | if (hwc1MinorVersion >= 3) { | ||
1451 | output << frectString(hwcLayer.sourceCropf) << '\n'; | ||
1452 | } else { | ||
1453 | output << rectString(hwcLayer.sourceCropi) << '\n'; | ||
1454 | } | ||
1455 | |||
1456 | output << fill << "Transform: " << hwc1TransformString(hwcLayer.transform); | ||
1457 | output << " Blend mode: " << hwc1BlendModeString(hwcLayer.blending); | ||
1458 | if (hwcLayer.planeAlpha != 0xFF) { | ||
1459 | output << " Alpha: " << alphaString(hwcLayer.planeAlpha / 255.0f); | ||
1460 | } | ||
1461 | output << '\n'; | ||
1462 | |||
1463 | if (hwcLayer.hints != 0) { | ||
1464 | output << fill << "Hints:"; | ||
1465 | if ((hwcLayer.hints & HWC_HINT_TRIPLE_BUFFER) != 0) { | ||
1466 | output << " TripleBuffer"; | ||
1467 | } | ||
1468 | if ((hwcLayer.hints & HWC_HINT_CLEAR_FB) != 0) { | ||
1469 | output << " ClearFB"; | ||
1470 | } | ||
1471 | output << '\n'; | ||
1472 | } | ||
1473 | |||
1474 | if (hwcLayer.flags != 0) { | ||
1475 | output << fill << "Flags:"; | ||
1476 | if ((hwcLayer.flags & HWC_SKIP_LAYER) != 0) { | ||
1477 | output << " SkipLayer"; | ||
1478 | } | ||
1479 | if ((hwcLayer.flags & HWC_IS_CURSOR_LAYER) != 0) { | ||
1480 | output << " IsCursorLayer"; | ||
1481 | } | ||
1482 | output << '\n'; | ||
1483 | } | ||
1484 | |||
1485 | return output.str(); | ||
1486 | } | ||
1487 | |||
1488 | static std::string to_string(const hwc_display_contents_1_t& hwcContents, | ||
1489 | int32_t hwc1MinorVersion) { | ||
1490 | const char* fill = " "; | ||
1491 | |||
1492 | std::stringstream output; | ||
1493 | output << fill << "Geometry changed: " << | ||
1494 | ((hwcContents.flags & HWC_GEOMETRY_CHANGED) != 0 ? "Y\n" : "N\n"); | ||
1495 | |||
1496 | output << fill << hwcContents.numHwLayers << " Layer" << | ||
1497 | ((hwcContents.numHwLayers == 1) ? "\n" : "s\n"); | ||
1498 | for (size_t layer = 0; layer < hwcContents.numHwLayers; ++layer) { | ||
1499 | output << fill << " Layer " << layer; | ||
1500 | output << to_string(hwcContents.hwLayers[layer], hwc1MinorVersion); | ||
1501 | } | ||
1502 | |||
1503 | if (hwcContents.outbuf != nullptr) { | ||
1504 | output << fill << "Output buffer: " << hwcContents.outbuf << "/" << | ||
1505 | hwcContents.outbufAcquireFenceFd << '\n'; | ||
1506 | } | ||
1507 | |||
1508 | return output.str(); | ||
1509 | } | ||
1510 | |||
1511 | std::string HWC2On1Adapter::Display::dump() const { | ||
1512 | std::unique_lock<std::recursive_mutex> lock(mStateMutex); | ||
1513 | |||
1514 | std::stringstream output; | ||
1515 | |||
1516 | output << " Display " << mId << ": "; | ||
1517 | output << to_string(mType) << " "; | ||
1518 | output << "HWC1 ID: " << mHwc1Id << " "; | ||
1519 | output << "Power mode: " << to_string(mPowerMode) << " "; | ||
1520 | output << "Vsync: " << to_string(mVsyncEnabled) << '\n'; | ||
1521 | |||
1522 | output << " Color modes [active]:"; | ||
1523 | for (const auto& mode : mColorModes) { | ||
1524 | if (mode == mActiveColorMode) { | ||
1525 | output << " [" << mode << ']'; | ||
1526 | } else { | ||
1527 | output << " " << mode; | ||
1528 | } | ||
1529 | } | ||
1530 | output << '\n'; | ||
1531 | |||
1532 | output << " " << mConfigs.size() << " Config" << | ||
1533 | (mConfigs.size() == 1 ? "" : "s") << " (* active)\n"; | ||
1534 | for (const auto& config : mConfigs) { | ||
1535 | output << (config == mActiveConfig ? " * " : " "); | ||
1536 | output << config->toString(true) << '\n'; | ||
1537 | } | ||
1538 | |||
1539 | output << " " << mLayers.size() << " Layer" << | ||
1540 | (mLayers.size() == 1 ? "" : "s") << '\n'; | ||
1541 | for (const auto& layer : mLayers) { | ||
1542 | output << layer->dump(); | ||
1543 | } | ||
1544 | |||
1545 | output << " Client target: " << mClientTarget.getBuffer() << '\n'; | ||
1546 | |||
1547 | if (mOutputBuffer.getBuffer() != nullptr) { | ||
1548 | output << " Output buffer: " << mOutputBuffer.getBuffer() << '\n'; | ||
1549 | } | ||
1550 | |||
1551 | if (mHwc1RequestedContents) { | ||
1552 | output << " Last requested HWC1 state\n"; | ||
1553 | output << to_string(*mHwc1RequestedContents, mDevice.mHwc1MinorVersion); | ||
1554 | } | ||
1555 | |||
1556 | return output.str(); | ||
1557 | } | ||
1558 | |||
1559 | hwc_rect_t* HWC2On1Adapter::Display::GetRects(size_t numRects) { | ||
1560 | if (numRects == 0) { | ||
1561 | return nullptr; | ||
1562 | } | ||
1563 | |||
1564 | if (numRects > mNumAvailableRects) { | ||
1565 | // This should NEVER happen since we calculated how many rects the | ||
1566 | // display would need. | ||
1567 | ALOGE("Rect allocation failure! SF is likely to crash soon!"); | ||
1568 | return nullptr; | ||
1569 | |||
1570 | } | ||
1571 | hwc_rect_t* rects = mNextAvailableRect; | ||
1572 | mNextAvailableRect += numRects; | ||
1573 | mNumAvailableRects -= numRects; | ||
1574 | return rects; | ||
1575 | } | ||
1576 | |||
1577 | hwc_display_contents_1* HWC2On1Adapter::Display::getDisplayContents() { | ||
1578 | return mHwc1RequestedContents.get(); | ||
1579 | } | ||
1580 | |||
1581 | void HWC2On1Adapter::Display::Config::setAttribute(HWC2::Attribute attribute, | ||
1582 | int32_t value) { | ||
1583 | mAttributes[attribute] = value; | ||
1584 | } | ||
1585 | |||
1586 | int32_t HWC2On1Adapter::Display::Config::getAttribute(Attribute attribute) const { | ||
1587 | if (mAttributes.count(attribute) == 0) { | ||
1588 | return -1; | ||
1589 | } | ||
1590 | return mAttributes.at(attribute); | ||
1591 | } | ||
1592 | |||
1593 | void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id) { | ||
1594 | android_color_mode_t colorMode = static_cast<android_color_mode_t>(getAttribute(ColorMode)); | ||
1595 | mHwc1Ids.emplace(colorMode, id); | ||
1596 | } | ||
1597 | |||
1598 | bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const { | ||
1599 | for (const auto& idPair : mHwc1Ids) { | ||
1600 | if (id == idPair.second) { | ||
1601 | return true; | ||
1602 | } | ||
1603 | } | ||
1604 | return false; | ||
1605 | } | ||
1606 | |||
1607 | Error HWC2On1Adapter::Display::Config::getColorModeForHwc1Id( | ||
1608 | uint32_t id, android_color_mode_t* outMode) const { | ||
1609 | for (const auto& idPair : mHwc1Ids) { | ||
1610 | if (id == idPair.second) { | ||
1611 | *outMode = idPair.first; | ||
1612 | return Error::None; | ||
1613 | } | ||
1614 | } | ||
1615 | ALOGE("Unable to find color mode for HWC ID %" PRIu32 " on config %u", id, mId); | ||
1616 | return Error::BadParameter; | ||
1617 | } | ||
1618 | |||
1619 | Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(android_color_mode_t mode, | ||
1620 | uint32_t* outId) const { | ||
1621 | for (const auto& idPair : mHwc1Ids) { | ||
1622 | if (mode == idPair.first) { | ||
1623 | *outId = idPair.second; | ||
1624 | return Error::None; | ||
1625 | } | ||
1626 | } | ||
1627 | ALOGE("Unable to find HWC1 ID for color mode %d on config %u", mode, mId); | ||
1628 | return Error::BadParameter; | ||
1629 | } | ||
1630 | |||
1631 | bool HWC2On1Adapter::Display::Config::merge(const Config& other) { | ||
1632 | auto attributes = {HWC2::Attribute::Width, HWC2::Attribute::Height, | ||
1633 | HWC2::Attribute::VsyncPeriod, HWC2::Attribute::DpiX, | ||
1634 | HWC2::Attribute::DpiY}; | ||
1635 | for (auto attribute : attributes) { | ||
1636 | if (getAttribute(attribute) != other.getAttribute(attribute)) { | ||
1637 | return false; | ||
1638 | } | ||
1639 | } | ||
1640 | android_color_mode_t otherColorMode = | ||
1641 | static_cast<android_color_mode_t>(other.getAttribute(ColorMode)); | ||
1642 | if (mHwc1Ids.count(otherColorMode) != 0) { | ||
1643 | ALOGE("Attempted to merge two configs (%u and %u) which appear to be " | ||
1644 | "identical", mHwc1Ids.at(otherColorMode), | ||
1645 | other.mHwc1Ids.at(otherColorMode)); | ||
1646 | return false; | ||
1647 | } | ||
1648 | mHwc1Ids.emplace(otherColorMode, | ||
1649 | other.mHwc1Ids.at(otherColorMode)); | ||
1650 | return true; | ||
1651 | } | ||
1652 | |||
1653 | std::set<android_color_mode_t> HWC2On1Adapter::Display::Config::getColorModes() const { | ||
1654 | std::set<android_color_mode_t> colorModes; | ||
1655 | for (const auto& idPair : mHwc1Ids) { | ||
1656 | colorModes.emplace(idPair.first); | ||
1657 | } | ||
1658 | return colorModes; | ||
1659 | } | ||
1660 | |||
1661 | std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const { | ||
1662 | std::string output; | ||
1663 | |||
1664 | const size_t BUFFER_SIZE = 100; | ||
1665 | char buffer[BUFFER_SIZE] = {}; | ||
1666 | auto writtenBytes = snprintf(buffer, BUFFER_SIZE, | ||
1667 | "%u x %u", mAttributes.at(HWC2::Attribute::Width), | ||
1668 | mAttributes.at(HWC2::Attribute::Height)); | ||
1669 | output.append(buffer, writtenBytes); | ||
1670 | |||
1671 | if (mAttributes.count(HWC2::Attribute::VsyncPeriod) != 0) { | ||
1672 | std::memset(buffer, 0, BUFFER_SIZE); | ||
1673 | writtenBytes = snprintf(buffer, BUFFER_SIZE, " @ %.1f Hz", | ||
1674 | 1e9 / mAttributes.at(HWC2::Attribute::VsyncPeriod)); | ||
1675 | output.append(buffer, writtenBytes); | ||
1676 | } | ||
1677 | |||
1678 | if (mAttributes.count(HWC2::Attribute::DpiX) != 0 && | ||
1679 | mAttributes.at(HWC2::Attribute::DpiX) != -1) { | ||
1680 | std::memset(buffer, 0, BUFFER_SIZE); | ||
1681 | writtenBytes = snprintf(buffer, BUFFER_SIZE, | ||
1682 | ", DPI: %.1f x %.1f", | ||
1683 | mAttributes.at(HWC2::Attribute::DpiX) / 1000.0f, | ||
1684 | mAttributes.at(HWC2::Attribute::DpiY) / 1000.0f); | ||
1685 | output.append(buffer, writtenBytes); | ||
1686 | } | ||
1687 | |||
1688 | std::memset(buffer, 0, BUFFER_SIZE); | ||
1689 | if (splitLine) { | ||
1690 | writtenBytes = snprintf(buffer, BUFFER_SIZE, | ||
1691 | "\n HWC1 ID/Color transform:"); | ||
1692 | } else { | ||
1693 | writtenBytes = snprintf(buffer, BUFFER_SIZE, | ||
1694 | ", HWC1 ID/Color transform:"); | ||
1695 | } | ||
1696 | output.append(buffer, writtenBytes); | ||
1697 | |||
1698 | |||
1699 | for (const auto& id : mHwc1Ids) { | ||
1700 | android_color_mode_t colorMode = id.first; | ||
1701 | uint32_t hwc1Id = id.second; | ||
1702 | std::memset(buffer, 0, BUFFER_SIZE); | ||
1703 | if (colorMode == mDisplay.mActiveColorMode) { | ||
1704 | writtenBytes = snprintf(buffer, BUFFER_SIZE, " [%u/%d]", hwc1Id, | ||
1705 | colorMode); | ||
1706 | } else { | ||
1707 | writtenBytes = snprintf(buffer, BUFFER_SIZE, " %u/%d", hwc1Id, | ||
1708 | colorMode); | ||
1709 | } | ||
1710 | output.append(buffer, writtenBytes); | ||
1711 | } | ||
1712 | |||
1713 | return output; | ||
1714 | } | ||
1715 | |||
1716 | std::shared_ptr<const HWC2On1Adapter::Display::Config> | ||
1717 | HWC2On1Adapter::Display::getConfig(hwc2_config_t configId) const { | ||
1718 | if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) { | ||
1719 | return nullptr; | ||
1720 | } | ||
1721 | return mConfigs[configId]; | ||
1722 | } | ||
1723 | |||
1724 | void HWC2On1Adapter::Display::populateColorModes() { | ||
1725 | mColorModes = mConfigs[0]->getColorModes(); | ||
1726 | for (const auto& config : mConfigs) { | ||
1727 | std::set<android_color_mode_t> intersection; | ||
1728 | auto configModes = config->getColorModes(); | ||
1729 | std::set_intersection(mColorModes.cbegin(), mColorModes.cend(), | ||
1730 | configModes.cbegin(), configModes.cend(), | ||
1731 | std::inserter(intersection, intersection.begin())); | ||
1732 | std::swap(intersection, mColorModes); | ||
1733 | } | ||
1734 | } | ||
1735 | |||
1736 | void HWC2On1Adapter::Display::initializeActiveConfig() { | ||
1737 | if (mDevice.mHwc1Device->getActiveConfig == nullptr) { | ||
1738 | ALOGV("getActiveConfig is null, choosing config 0"); | ||
1739 | mActiveConfig = mConfigs[0]; | ||
1740 | mActiveColorMode = HAL_COLOR_MODE_NATIVE; | ||
1741 | return; | ||
1742 | } | ||
1743 | |||
1744 | auto activeConfig = mDevice.mHwc1Device->getActiveConfig( | ||
1745 | mDevice.mHwc1Device, mHwc1Id); | ||
1746 | |||
1747 | // Some devices startup without an activeConfig: | ||
1748 | // We need to set one ourselves. | ||
1749 | if (activeConfig == HWC_ERROR) { | ||
1750 | ALOGV("There is no active configuration: Picking the first one: 0."); | ||
1751 | const int defaultIndex = 0; | ||
1752 | mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device, mHwc1Id, defaultIndex); | ||
1753 | activeConfig = defaultIndex; | ||
1754 | } | ||
1755 | |||
1756 | for (const auto& config : mConfigs) { | ||
1757 | if (config->hasHwc1Id(activeConfig)) { | ||
1758 | ALOGE("Setting active config to %d for HWC1 config %u", config->getId(), activeConfig); | ||
1759 | mActiveConfig = config; | ||
1760 | if (config->getColorModeForHwc1Id(activeConfig, &mActiveColorMode) != Error::None) { | ||
1761 | // This should never happen since we checked for the config's presence before | ||
1762 | // setting it as active. | ||
1763 | ALOGE("Unable to find color mode for active HWC1 config %d", config->getId()); | ||
1764 | mActiveColorMode = HAL_COLOR_MODE_NATIVE; | ||
1765 | } | ||
1766 | break; | ||
1767 | } | ||
1768 | } | ||
1769 | if (!mActiveConfig) { | ||
1770 | ALOGV("Unable to find active HWC1 config %u, defaulting to " | ||
1771 | "config 0", activeConfig); | ||
1772 | mActiveConfig = mConfigs[0]; | ||
1773 | mActiveColorMode = HAL_COLOR_MODE_NATIVE; | ||
1774 | } | ||
1775 | |||
1776 | |||
1777 | |||
1778 | |||
1779 | } | ||
1780 | |||
1781 | void HWC2On1Adapter::Display::allocateRequestedContents() { | ||
1782 | // What needs to be allocated: | ||
1783 | // 1 hwc_display_contents_1_t | ||
1784 | // 1 hwc_layer_1_t for each layer | ||
1785 | // 1 hwc_rect_t for each layer's surfaceDamage | ||
1786 | // 1 hwc_rect_t for each layer's visibleRegion | ||
1787 | // 1 hwc_layer_1_t for the framebuffer | ||
1788 | // 1 hwc_rect_t for the framebuffer's visibleRegion | ||
1789 | |||
1790 | // Count # of surfaceDamage | ||
1791 | size_t numSurfaceDamages = 0; | ||
1792 | for (const auto& layer : mLayers) { | ||
1793 | numSurfaceDamages += layer->getNumSurfaceDamages(); | ||
1794 | } | ||
1795 | |||
1796 | // Count # of visibleRegions (start at 1 for mandatory framebuffer target | ||
1797 | // region) | ||
1798 | size_t numVisibleRegion = 1; | ||
1799 | for (const auto& layer : mLayers) { | ||
1800 | numVisibleRegion += layer->getNumVisibleRegions(); | ||
1801 | } | ||
1802 | |||
1803 | size_t numRects = numVisibleRegion + numSurfaceDamages; | ||
1804 | auto numLayers = mLayers.size() + 1; | ||
1805 | size_t size = sizeof(hwc_display_contents_1_t) + | ||
1806 | sizeof(hwc_layer_1_t) * numLayers + | ||
1807 | sizeof(hwc_rect_t) * numRects; | ||
1808 | auto contents = static_cast<hwc_display_contents_1_t*>(std::calloc(size, 1)); | ||
1809 | mHwc1RequestedContents.reset(contents); | ||
1810 | mNextAvailableRect = reinterpret_cast<hwc_rect_t*>(&contents->hwLayers[numLayers]); | ||
1811 | mNumAvailableRects = numRects; | ||
1812 | } | ||
1813 | |||
1814 | void HWC2On1Adapter::Display::assignHwc1LayerIds() { | ||
1815 | mHwc1LayerMap.clear(); | ||
1816 | size_t nextHwc1Id = 0; | ||
1817 | for (auto& layer : mLayers) { | ||
1818 | mHwc1LayerMap[nextHwc1Id] = layer; | ||
1819 | layer->setHwc1Id(nextHwc1Id++); | ||
1820 | } | ||
1821 | } | ||
1822 | |||
1823 | void HWC2On1Adapter::Display::updateTypeChanges(const hwc_layer_1_t& hwc1Layer, | ||
1824 | const Layer& layer) { | ||
1825 | auto layerId = layer.getId(); | ||
1826 | switch (hwc1Layer.compositionType) { | ||
1827 | case HWC_FRAMEBUFFER: | ||
1828 | if (layer.getCompositionType() != Composition::Client) { | ||
1829 | mChanges->addTypeChange(layerId, Composition::Client); | ||
1830 | } | ||
1831 | break; | ||
1832 | case HWC_OVERLAY: | ||
1833 | if (layer.getCompositionType() != Composition::Device) { | ||
1834 | mChanges->addTypeChange(layerId, Composition::Device); | ||
1835 | } | ||
1836 | break; | ||
1837 | case HWC_BACKGROUND: | ||
1838 | ALOGE_IF(layer.getCompositionType() != Composition::SolidColor, | ||
1839 | "updateTypeChanges: HWC1 requested BACKGROUND, but HWC2" | ||
1840 | " wasn't expecting SolidColor"); | ||
1841 | break; | ||
1842 | case HWC_FRAMEBUFFER_TARGET: | ||
1843 | // Do nothing, since it shouldn't be modified by HWC1 | ||
1844 | break; | ||
1845 | case HWC_SIDEBAND: | ||
1846 | ALOGE_IF(layer.getCompositionType() != Composition::Sideband, | ||
1847 | "updateTypeChanges: HWC1 requested SIDEBAND, but HWC2" | ||
1848 | " wasn't expecting Sideband"); | ||
1849 | break; | ||
1850 | case HWC_CURSOR_OVERLAY: | ||
1851 | ALOGE_IF(layer.getCompositionType() != Composition::Cursor, | ||
1852 | "updateTypeChanges: HWC1 requested CURSOR_OVERLAY, but" | ||
1853 | " HWC2 wasn't expecting Cursor"); | ||
1854 | break; | ||
1855 | } | ||
1856 | } | ||
1857 | |||
1858 | void HWC2On1Adapter::Display::updateLayerRequests( | ||
1859 | const hwc_layer_1_t& hwc1Layer, const Layer& layer) { | ||
1860 | if ((hwc1Layer.hints & HWC_HINT_CLEAR_FB) != 0) { | ||
1861 | mChanges->addLayerRequest(layer.getId(), | ||
1862 | LayerRequest::ClearClientTarget); | ||
1863 | } | ||
1864 | } | ||
1865 | |||
1866 | void HWC2On1Adapter::Display::prepareFramebufferTarget() { | ||
1867 | // We check that mActiveConfig is valid in Display::prepare | ||
1868 | int32_t width = mActiveConfig->getAttribute(Attribute::Width); | ||
1869 | int32_t height = mActiveConfig->getAttribute(Attribute::Height); | ||
1870 | |||
1871 | auto& hwc1Target = mHwc1RequestedContents->hwLayers[mLayers.size()]; | ||
1872 | hwc1Target.compositionType = HWC_FRAMEBUFFER_TARGET; | ||
1873 | hwc1Target.releaseFenceFd = -1; | ||
1874 | hwc1Target.hints = 0; | ||
1875 | hwc1Target.flags = 0; | ||
1876 | hwc1Target.transform = 0; | ||
1877 | hwc1Target.blending = HWC_BLENDING_PREMULT; | ||
1878 | if (mDevice.getHwc1MinorVersion() < 3) { | ||
1879 | hwc1Target.sourceCropi = {0, 0, width, height}; | ||
1880 | } else { | ||
1881 | hwc1Target.sourceCropf = {0.0f, 0.0f, static_cast<float>(width), | ||
1882 | static_cast<float>(height)}; | ||
1883 | } | ||
1884 | hwc1Target.displayFrame = {0, 0, width, height}; | ||
1885 | hwc1Target.planeAlpha = 255; | ||
1886 | |||
1887 | hwc1Target.visibleRegionScreen.numRects = 1; | ||
1888 | hwc_rect_t* rects = GetRects(1); | ||
1889 | rects[0].left = 0; | ||
1890 | rects[0].top = 0; | ||
1891 | rects[0].right = width; | ||
1892 | rects[0].bottom = height; | ||
1893 | hwc1Target.visibleRegionScreen.rects = rects; | ||
1894 | |||
1895 | // We will set this to the correct value in set | ||
1896 | hwc1Target.acquireFenceFd = -1; | ||
1897 | } | ||
1898 | |||
1899 | // Layer functions | ||
1900 | |||
1901 | std::atomic<hwc2_layer_t> HWC2On1Adapter::Layer::sNextId(1); | ||
1902 | |||
1903 | HWC2On1Adapter::Layer::Layer(Display& display) | ||
1904 | : mId(sNextId++), | ||
1905 | mDisplay(display), | ||
1906 | mBuffer(), | ||
1907 | mSurfaceDamage(), | ||
1908 | mBlendMode(BlendMode::None), | ||
1909 | mColor({0, 0, 0, 0}), | ||
1910 | mCompositionType(Composition::Invalid), | ||
1911 | mDisplayFrame({0, 0, -1, -1}), | ||
1912 | mPlaneAlpha(0.0f), | ||
1913 | mSidebandStream(nullptr), | ||
1914 | mSourceCrop({0.0f, 0.0f, -1.0f, -1.0f}), | ||
1915 | mTransform(Transform::None), | ||
1916 | mVisibleRegion(), | ||
1917 | mZ(0), | ||
1918 | mReleaseFence(), | ||
1919 | mHwc1Id(0), | ||
1920 | mHasUnsupportedPlaneAlpha(false) {} | ||
1921 | |||
1922 | bool HWC2On1Adapter::SortLayersByZ::operator()( | ||
1923 | const std::shared_ptr<Layer>& lhs, const std::shared_ptr<Layer>& rhs) { | ||
1924 | return lhs->getZ() < rhs->getZ(); | ||
1925 | } | ||
1926 | |||
1927 | Error HWC2On1Adapter::Layer::setBuffer(buffer_handle_t buffer, | ||
1928 | int32_t acquireFence) { | ||
1929 | ALOGV("Setting acquireFence to %d for layer %" PRIu64, acquireFence, mId); | ||
1930 | mBuffer.setBuffer(buffer); | ||
1931 | mBuffer.setFence(acquireFence); | ||
1932 | return Error::None; | ||
1933 | } | ||
1934 | |||
1935 | Error HWC2On1Adapter::Layer::setCursorPosition(int32_t x, int32_t y) { | ||
1936 | if (mCompositionType != Composition::Cursor) { | ||
1937 | return Error::BadLayer; | ||
1938 | } | ||
1939 | |||
1940 | if (mDisplay.hasChanges()) { | ||
1941 | return Error::NotValidated; | ||
1942 | } | ||
1943 | |||
1944 | auto displayId = mDisplay.getHwc1Id(); | ||
1945 | auto hwc1Device = mDisplay.getDevice().getHwc1Device(); | ||
1946 | hwc1Device->setCursorPositionAsync(hwc1Device, displayId, x, y); | ||
1947 | return Error::None; | ||
1948 | } | ||
1949 | |||
1950 | Error HWC2On1Adapter::Layer::setSurfaceDamage(hwc_region_t damage) { | ||
1951 | // HWC1 supports surface damage starting only with version 1.5. | ||
1952 | if (mDisplay.getDevice().mHwc1MinorVersion < 5) { | ||
1953 | return Error::None; | ||
1954 | } | ||
1955 | mSurfaceDamage.resize(damage.numRects); | ||
1956 | std::copy_n(damage.rects, damage.numRects, mSurfaceDamage.begin()); | ||
1957 | return Error::None; | ||
1958 | } | ||
1959 | |||
1960 | // Layer state functions | ||
1961 | |||
1962 | Error HWC2On1Adapter::Layer::setBlendMode(BlendMode mode) { | ||
1963 | mBlendMode = mode; | ||
1964 | mDisplay.markGeometryChanged(); | ||
1965 | return Error::None; | ||
1966 | } | ||
1967 | |||
1968 | Error HWC2On1Adapter::Layer::setColor(hwc_color_t color) { | ||
1969 | mColor = color; | ||
1970 | mDisplay.markGeometryChanged(); | ||
1971 | return Error::None; | ||
1972 | } | ||
1973 | |||
1974 | Error HWC2On1Adapter::Layer::setCompositionType(Composition type) { | ||
1975 | mCompositionType = type; | ||
1976 | mDisplay.markGeometryChanged(); | ||
1977 | return Error::None; | ||
1978 | } | ||
1979 | |||
1980 | Error HWC2On1Adapter::Layer::setDataspace(android_dataspace_t) { | ||
1981 | return Error::None; | ||
1982 | } | ||
1983 | |||
1984 | Error HWC2On1Adapter::Layer::setDisplayFrame(hwc_rect_t frame) { | ||
1985 | mDisplayFrame = frame; | ||
1986 | mDisplay.markGeometryChanged(); | ||
1987 | return Error::None; | ||
1988 | } | ||
1989 | |||
1990 | Error HWC2On1Adapter::Layer::setPlaneAlpha(float alpha) { | ||
1991 | mPlaneAlpha = alpha; | ||
1992 | mDisplay.markGeometryChanged(); | ||
1993 | return Error::None; | ||
1994 | } | ||
1995 | |||
1996 | Error HWC2On1Adapter::Layer::setSidebandStream(const native_handle_t* stream) { | ||
1997 | mSidebandStream = stream; | ||
1998 | mDisplay.markGeometryChanged(); | ||
1999 | return Error::None; | ||
2000 | } | ||
2001 | |||
2002 | Error HWC2On1Adapter::Layer::setSourceCrop(hwc_frect_t crop) { | ||
2003 | mSourceCrop = crop; | ||
2004 | mDisplay.markGeometryChanged(); | ||
2005 | return Error::None; | ||
2006 | } | ||
2007 | |||
2008 | Error HWC2On1Adapter::Layer::setTransform(Transform transform) { | ||
2009 | mTransform = transform; | ||
2010 | mDisplay.markGeometryChanged(); | ||
2011 | return Error::None; | ||
2012 | } | ||
2013 | |||
2014 | static bool compareRects(const hwc_rect_t& rect1, const hwc_rect_t& rect2) { | ||
2015 | return rect1.left == rect2.left && | ||
2016 | rect1.right == rect2.right && | ||
2017 | rect1.top == rect2.top && | ||
2018 | rect1.bottom == rect2.bottom; | ||
2019 | } | ||
2020 | |||
2021 | Error HWC2On1Adapter::Layer::setVisibleRegion(hwc_region_t visible) { | ||
2022 | if ((getNumVisibleRegions() != visible.numRects) || | ||
2023 | !std::equal(mVisibleRegion.begin(), mVisibleRegion.end(), visible.rects, | ||
2024 | compareRects)) { | ||
2025 | mVisibleRegion.resize(visible.numRects); | ||
2026 | std::copy_n(visible.rects, visible.numRects, mVisibleRegion.begin()); | ||
2027 | mDisplay.markGeometryChanged(); | ||
2028 | } | ||
2029 | return Error::None; | ||
2030 | } | ||
2031 | |||
2032 | Error HWC2On1Adapter::Layer::setZ(uint32_t z) { | ||
2033 | mZ = z; | ||
2034 | return Error::None; | ||
2035 | } | ||
2036 | |||
2037 | void HWC2On1Adapter::Layer::addReleaseFence(int fenceFd) { | ||
2038 | ALOGV("addReleaseFence %d to layer %" PRIu64, fenceFd, mId); | ||
2039 | mReleaseFence.add(fenceFd); | ||
2040 | } | ||
2041 | |||
2042 | const sp<MiniFence>& HWC2On1Adapter::Layer::getReleaseFence() const { | ||
2043 | return mReleaseFence.get(); | ||
2044 | } | ||
2045 | |||
2046 | void HWC2On1Adapter::Layer::applyState(hwc_layer_1_t& hwc1Layer) { | ||
2047 | applyCommonState(hwc1Layer); | ||
2048 | applyCompositionType(hwc1Layer); | ||
2049 | switch (mCompositionType) { | ||
2050 | case Composition::SolidColor : applySolidColorState(hwc1Layer); break; | ||
2051 | case Composition::Sideband : applySidebandState(hwc1Layer); break; | ||
2052 | default: applyBufferState(hwc1Layer); break; | ||
2053 | } | ||
2054 | } | ||
2055 | |||
2056 | static std::string regionStrings(const std::vector<hwc_rect_t>& visibleRegion, | ||
2057 | const std::vector<hwc_rect_t>& surfaceDamage) { | ||
2058 | std::string regions; | ||
2059 | regions += " Visible Region"; | ||
2060 | regions.resize(40, ' '); | ||
2061 | regions += "Surface Damage\n"; | ||
2062 | |||
2063 | size_t numPrinted = 0; | ||
2064 | size_t maxSize = std::max(visibleRegion.size(), surfaceDamage.size()); | ||
2065 | while (numPrinted < maxSize) { | ||
2066 | std::string line(" "); | ||
2067 | if (visibleRegion.empty() && numPrinted == 0) { | ||
2068 | line += "None"; | ||
2069 | } else if (numPrinted < visibleRegion.size()) { | ||
2070 | line += rectString(visibleRegion[numPrinted]); | ||
2071 | } | ||
2072 | line.resize(40, ' '); | ||
2073 | if (surfaceDamage.empty() && numPrinted == 0) { | ||
2074 | line += "None"; | ||
2075 | } else if (numPrinted < surfaceDamage.size()) { | ||
2076 | line += rectString(surfaceDamage[numPrinted]); | ||
2077 | } | ||
2078 | line += '\n'; | ||
2079 | regions += line; | ||
2080 | ++numPrinted; | ||
2081 | } | ||
2082 | return regions; | ||
2083 | } | ||
2084 | |||
2085 | std::string HWC2On1Adapter::Layer::dump() const { | ||
2086 | std::stringstream output; | ||
2087 | const char* fill = " "; | ||
2088 | |||
2089 | output << fill << to_string(mCompositionType); | ||
2090 | output << " Layer HWC2/1: " << mId << "/" << mHwc1Id << " "; | ||
2091 | output << "Z: " << mZ; | ||
2092 | if (mCompositionType == HWC2::Composition::SolidColor) { | ||
2093 | output << " " << colorString(mColor); | ||
2094 | } else if (mCompositionType == HWC2::Composition::Sideband) { | ||
2095 | output << " Handle: " << mSidebandStream << '\n'; | ||
2096 | } else { | ||
2097 | output << " Buffer: " << mBuffer.getBuffer() << "/" << | ||
2098 | mBuffer.getFence() << '\n'; | ||
2099 | output << fill << " Display frame [LTRB]: " << | ||
2100 | rectString(mDisplayFrame) << '\n'; | ||
2101 | output << fill << " Source crop: " << | ||
2102 | frectString(mSourceCrop) << '\n'; | ||
2103 | output << fill << " Transform: " << to_string(mTransform); | ||
2104 | output << " Blend mode: " << to_string(mBlendMode); | ||
2105 | if (mPlaneAlpha != 1.0f) { | ||
2106 | output << " Alpha: " << | ||
2107 | alphaString(mPlaneAlpha) << '\n'; | ||
2108 | } else { | ||
2109 | output << '\n'; | ||
2110 | } | ||
2111 | output << regionStrings(mVisibleRegion, mSurfaceDamage); | ||
2112 | } | ||
2113 | return output.str(); | ||
2114 | } | ||
2115 | |||
2116 | static int getHwc1Blending(HWC2::BlendMode blendMode) { | ||
2117 | switch (blendMode) { | ||
2118 | case BlendMode::Coverage: return HWC_BLENDING_COVERAGE; | ||
2119 | case BlendMode::Premultiplied: return HWC_BLENDING_PREMULT; | ||
2120 | default: return HWC_BLENDING_NONE; | ||
2121 | } | ||
2122 | } | ||
2123 | |||
2124 | void HWC2On1Adapter::Layer::applyCommonState(hwc_layer_1_t& hwc1Layer) { | ||
2125 | auto minorVersion = mDisplay.getDevice().getHwc1MinorVersion(); | ||
2126 | hwc1Layer.blending = getHwc1Blending(mBlendMode); | ||
2127 | hwc1Layer.displayFrame = mDisplayFrame; | ||
2128 | |||
2129 | auto pendingAlpha = mPlaneAlpha; | ||
2130 | if (minorVersion < 2) { | ||
2131 | mHasUnsupportedPlaneAlpha = pendingAlpha < 1.0f; | ||
2132 | } else { | ||
2133 | hwc1Layer.planeAlpha = | ||
2134 | static_cast<uint8_t>(255.0f * pendingAlpha + 0.5f); | ||
2135 | } | ||
2136 | |||
2137 | if (minorVersion < 3) { | ||
2138 | auto pending = mSourceCrop; | ||
2139 | hwc1Layer.sourceCropi.left = | ||
2140 | static_cast<int32_t>(std::ceil(pending.left)); | ||
2141 | hwc1Layer.sourceCropi.top = | ||
2142 | static_cast<int32_t>(std::ceil(pending.top)); | ||
2143 | hwc1Layer.sourceCropi.right = | ||
2144 | static_cast<int32_t>(std::floor(pending.right)); | ||
2145 | hwc1Layer.sourceCropi.bottom = | ||
2146 | static_cast<int32_t>(std::floor(pending.bottom)); | ||
2147 | } else { | ||
2148 | hwc1Layer.sourceCropf = mSourceCrop; | ||
2149 | } | ||
2150 | |||
2151 | hwc1Layer.transform = static_cast<uint32_t>(mTransform); | ||
2152 | |||
2153 | auto& hwc1VisibleRegion = hwc1Layer.visibleRegionScreen; | ||
2154 | hwc1VisibleRegion.numRects = mVisibleRegion.size(); | ||
2155 | hwc_rect_t* rects = mDisplay.GetRects(hwc1VisibleRegion.numRects); | ||
2156 | hwc1VisibleRegion.rects = rects; | ||
2157 | for (size_t i = 0; i < mVisibleRegion.size(); i++) { | ||
2158 | rects[i] = mVisibleRegion[i]; | ||
2159 | } | ||
2160 | } | ||
2161 | |||
2162 | void HWC2On1Adapter::Layer::applySolidColorState(hwc_layer_1_t& hwc1Layer) { | ||
2163 | // If the device does not support background color it is likely to make | ||
2164 | // assumption regarding backgroundColor and handle (both fields occupy | ||
2165 | // the same location in hwc_layer_1_t union). | ||
2166 | // To not confuse these devices we don't set background color and we | ||
2167 | // make sure handle is a null pointer. | ||
2168 | if (hasUnsupportedBackgroundColor()) { | ||
2169 | hwc1Layer.handle = nullptr; | ||
2170 | } else { | ||
2171 | hwc1Layer.backgroundColor = mColor; | ||
2172 | } | ||
2173 | } | ||
2174 | |||
2175 | void HWC2On1Adapter::Layer::applySidebandState(hwc_layer_1_t& hwc1Layer) { | ||
2176 | hwc1Layer.sidebandStream = mSidebandStream; | ||
2177 | } | ||
2178 | |||
2179 | void HWC2On1Adapter::Layer::applyBufferState(hwc_layer_1_t& hwc1Layer) { | ||
2180 | hwc1Layer.handle = mBuffer.getBuffer(); | ||
2181 | hwc1Layer.acquireFenceFd = mBuffer.getFence(); | ||
2182 | } | ||
2183 | |||
2184 | void HWC2On1Adapter::Layer::applyCompositionType(hwc_layer_1_t& hwc1Layer) { | ||
2185 | // HWC1 never supports color transforms or dataspaces and only sometimes | ||
2186 | // supports plane alpha (depending on the version). These require us to drop | ||
2187 | // some or all layers to client composition. | ||
2188 | if (mHasUnsupportedPlaneAlpha || mDisplay.hasColorTransform() || | ||
2189 | hasUnsupportedBackgroundColor()) { | ||
2190 | hwc1Layer.compositionType = HWC_FRAMEBUFFER; | ||
2191 | hwc1Layer.flags = HWC_SKIP_LAYER; | ||
2192 | return; | ||
2193 | } | ||
2194 | |||
2195 | hwc1Layer.flags = 0; | ||
2196 | switch (mCompositionType) { | ||
2197 | case Composition::Client: | ||
2198 | hwc1Layer.compositionType = HWC_FRAMEBUFFER; | ||
2199 | hwc1Layer.flags |= HWC_SKIP_LAYER; | ||
2200 | break; | ||
2201 | case Composition::Device: | ||
2202 | hwc1Layer.compositionType = HWC_FRAMEBUFFER; | ||
2203 | break; | ||
2204 | case Composition::SolidColor: | ||
2205 | // In theory the following line should work, but since the HWC1 | ||
2206 | // version of SurfaceFlinger never used HWC_BACKGROUND, HWC1 | ||
2207 | // devices may not work correctly. To be on the safe side, we | ||
2208 | // fall back to client composition. | ||
2209 | // | ||
2210 | // hwc1Layer.compositionType = HWC_BACKGROUND; | ||
2211 | hwc1Layer.compositionType = HWC_FRAMEBUFFER; | ||
2212 | hwc1Layer.flags |= HWC_SKIP_LAYER; | ||
2213 | break; | ||
2214 | case Composition::Cursor: | ||
2215 | hwc1Layer.compositionType = HWC_FRAMEBUFFER; | ||
2216 | if (mDisplay.getDevice().getHwc1MinorVersion() >= 4) { | ||
2217 | hwc1Layer.hints |= HWC_IS_CURSOR_LAYER; | ||
2218 | } | ||
2219 | break; | ||
2220 | case Composition::Sideband: | ||
2221 | if (mDisplay.getDevice().getHwc1MinorVersion() < 4) { | ||
2222 | hwc1Layer.compositionType = HWC_SIDEBAND; | ||
2223 | } else { | ||
2224 | hwc1Layer.compositionType = HWC_FRAMEBUFFER; | ||
2225 | hwc1Layer.flags |= HWC_SKIP_LAYER; | ||
2226 | } | ||
2227 | break; | ||
2228 | default: | ||
2229 | hwc1Layer.compositionType = HWC_FRAMEBUFFER; | ||
2230 | hwc1Layer.flags |= HWC_SKIP_LAYER; | ||
2231 | break; | ||
2232 | } | ||
2233 | ALOGV("Layer %" PRIu64 " %s set to %d", mId, | ||
2234 | to_string(mCompositionType).c_str(), | ||
2235 | hwc1Layer.compositionType); | ||
2236 | ALOGV_IF(hwc1Layer.flags & HWC_SKIP_LAYER, " and skipping"); | ||
2237 | } | ||
2238 | |||
2239 | // Adapter helpers | ||
2240 | |||
2241 | void HWC2On1Adapter::populateCapabilities() { | ||
2242 | if (mHwc1MinorVersion >= 3U) { | ||
2243 | int supportedTypes = 0; | ||
2244 | auto result = mHwc1Device->query(mHwc1Device, | ||
2245 | HWC_DISPLAY_TYPES_SUPPORTED, &supportedTypes); | ||
2246 | if ((result == 0) && ((supportedTypes & HWC_DISPLAY_VIRTUAL_BIT) != 0)) { | ||
2247 | ALOGI("Found support for HWC virtual displays"); | ||
2248 | mHwc1SupportsVirtualDisplays = true; | ||
2249 | } | ||
2250 | } | ||
2251 | if (mHwc1MinorVersion >= 4U) { | ||
2252 | mCapabilities.insert(Capability::SidebandStream); | ||
2253 | } | ||
2254 | |||
2255 | // Check for HWC background color layer support. | ||
2256 | if (mHwc1MinorVersion >= 1U) { | ||
2257 | int backgroundColorSupported = 0; | ||
2258 | auto result = mHwc1Device->query(mHwc1Device, | ||
2259 | HWC_BACKGROUND_LAYER_SUPPORTED, | ||
2260 | &backgroundColorSupported); | ||
2261 | if ((result == 0) && (backgroundColorSupported == 1)) { | ||
2262 | ALOGV("Found support for HWC background color"); | ||
2263 | mHwc1SupportsBackgroundColor = true; | ||
2264 | } | ||
2265 | } | ||
2266 | |||
2267 | // Some devices might have HWC1 retire fences that accurately emulate | ||
2268 | // HWC2 present fences when they are deferred, but it's not very reliable. | ||
2269 | // To be safe, we indicate PresentFenceIsNotReliable for all HWC1 devices. | ||
2270 | mCapabilities.insert(Capability::PresentFenceIsNotReliable); | ||
2271 | } | ||
2272 | |||
2273 | HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id) { | ||
2274 | std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); | ||
2275 | |||
2276 | auto display = mDisplays.find(id); | ||
2277 | if (display == mDisplays.end()) { | ||
2278 | return nullptr; | ||
2279 | } | ||
2280 | |||
2281 | return display->second.get(); | ||
2282 | } | ||
2283 | |||
2284 | std::tuple<HWC2On1Adapter::Layer*, Error> HWC2On1Adapter::getLayer( | ||
2285 | hwc2_display_t displayId, hwc2_layer_t layerId) { | ||
2286 | auto display = getDisplay(displayId); | ||
2287 | if (!display) { | ||
2288 | return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadDisplay); | ||
2289 | } | ||
2290 | |||
2291 | auto layerEntry = mLayers.find(layerId); | ||
2292 | if (layerEntry == mLayers.end()) { | ||
2293 | return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadLayer); | ||
2294 | } | ||
2295 | |||
2296 | auto layer = layerEntry->second; | ||
2297 | if (layer->getDisplay().getId() != displayId) { | ||
2298 | return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadLayer); | ||
2299 | } | ||
2300 | return std::make_tuple(layer.get(), Error::None); | ||
2301 | } | ||
2302 | |||
2303 | void HWC2On1Adapter::populatePrimary() { | ||
2304 | std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); | ||
2305 | |||
2306 | auto display = std::make_shared<Display>(*this, HWC2::DisplayType::Physical); | ||
2307 | mHwc1DisplayMap[HWC_DISPLAY_PRIMARY] = display->getId(); | ||
2308 | display->setHwc1Id(HWC_DISPLAY_PRIMARY); | ||
2309 | display->populateConfigs(); | ||
2310 | mDisplays.emplace(display->getId(), std::move(display)); | ||
2311 | } | ||
2312 | |||
2313 | bool HWC2On1Adapter::prepareAllDisplays() { | ||
2314 | ATRACE_CALL(); | ||
2315 | |||
2316 | std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); | ||
2317 | |||
2318 | for (const auto& displayPair : mDisplays) { | ||
2319 | auto& display = displayPair.second; | ||
2320 | if (!display->prepare()) { | ||
2321 | return false; | ||
2322 | } | ||
2323 | } | ||
2324 | |||
2325 | if (mHwc1DisplayMap.count(HWC_DISPLAY_PRIMARY) == 0) { | ||
2326 | ALOGE("prepareAllDisplays: Unable to find primary HWC1 display"); | ||
2327 | return false; | ||
2328 | } | ||
2329 | |||
2330 | // Build an array of hwc_display_contents_1 to call prepare() on HWC1. | ||
2331 | mHwc1Contents.clear(); | ||
2332 | |||
2333 | // Always push the primary display | ||
2334 | auto primaryDisplayId = mHwc1DisplayMap[HWC_DISPLAY_PRIMARY]; | ||
2335 | auto& primaryDisplay = mDisplays[primaryDisplayId]; | ||
2336 | mHwc1Contents.push_back(primaryDisplay->getDisplayContents()); | ||
2337 | |||
2338 | // Push the external display, if present | ||
2339 | if (mHwc1DisplayMap.count(HWC_DISPLAY_EXTERNAL) != 0) { | ||
2340 | auto externalDisplayId = mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL]; | ||
2341 | auto& externalDisplay = mDisplays[externalDisplayId]; | ||
2342 | mHwc1Contents.push_back(externalDisplay->getDisplayContents()); | ||
2343 | } else { | ||
2344 | // Even if an external display isn't present, we still need to send | ||
2345 | // at least two displays down to HWC1 | ||
2346 | mHwc1Contents.push_back(nullptr); | ||
2347 | } | ||
2348 | |||
2349 | // Push the hardware virtual display, if supported and present | ||
2350 | if (mHwc1MinorVersion >= 3) { | ||
2351 | if (mHwc1DisplayMap.count(HWC_DISPLAY_VIRTUAL) != 0) { | ||
2352 | auto virtualDisplayId = mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL]; | ||
2353 | auto& virtualDisplay = mDisplays[virtualDisplayId]; | ||
2354 | mHwc1Contents.push_back(virtualDisplay->getDisplayContents()); | ||
2355 | } else { | ||
2356 | mHwc1Contents.push_back(nullptr); | ||
2357 | } | ||
2358 | } | ||
2359 | |||
2360 | for (auto& displayContents : mHwc1Contents) { | ||
2361 | if (!displayContents) { | ||
2362 | continue; | ||
2363 | } | ||
2364 | |||
2365 | ALOGV("Display %zd layers:", mHwc1Contents.size() - 1); | ||
2366 | for (size_t l = 0; l < displayContents->numHwLayers; ++l) { | ||
2367 | auto& layer = displayContents->hwLayers[l]; | ||
2368 | ALOGV(" %zd: %d", l, layer.compositionType); | ||
2369 | } | ||
2370 | } | ||
2371 | |||
2372 | ALOGV("Calling HWC1 prepare"); | ||
2373 | { | ||
2374 | ATRACE_NAME("HWC1 prepare"); | ||
2375 | mHwc1Device->prepare(mHwc1Device, mHwc1Contents.size(), | ||
2376 | mHwc1Contents.data()); | ||
2377 | } | ||
2378 | |||
2379 | for (size_t c = 0; c < mHwc1Contents.size(); ++c) { | ||
2380 | auto& contents = mHwc1Contents[c]; | ||
2381 | if (!contents) { | ||
2382 | continue; | ||
2383 | } | ||
2384 | ALOGV("Display %zd layers:", c); | ||
2385 | for (size_t l = 0; l < contents->numHwLayers; ++l) { | ||
2386 | ALOGV(" %zd: %d", l, contents->hwLayers[l].compositionType); | ||
2387 | } | ||
2388 | } | ||
2389 | |||
2390 | // Return the received contents to their respective displays | ||
2391 | for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) { | ||
2392 | if (mHwc1Contents[hwc1Id] == nullptr) { | ||
2393 | continue; | ||
2394 | } | ||
2395 | |||
2396 | auto displayId = mHwc1DisplayMap[hwc1Id]; | ||
2397 | auto& display = mDisplays[displayId]; | ||
2398 | display->generateChanges(); | ||
2399 | } | ||
2400 | |||
2401 | return true; | ||
2402 | } | ||
2403 | |||
2404 | void dumpHWC1Message(hwc_composer_device_1* device, size_t numDisplays, | ||
2405 | hwc_display_contents_1_t** displays) { | ||
2406 | ALOGV("*****************************"); | ||
2407 | size_t displayId = 0; | ||
2408 | while (displayId < numDisplays) { | ||
2409 | hwc_display_contents_1_t* display = displays[displayId]; | ||
2410 | |||
2411 | ALOGV("hwc_display_contents_1_t[%zu] @0x%p", displayId, display); | ||
2412 | if (display == nullptr) { | ||
2413 | displayId++; | ||
2414 | continue; | ||
2415 | } | ||
2416 | ALOGV(" retirefd:0x%08x", display->retireFenceFd); | ||
2417 | ALOGV(" outbuf :0x%p", display->outbuf); | ||
2418 | ALOGV(" outbuffd:0x%08x", display->outbufAcquireFenceFd); | ||
2419 | ALOGV(" flags :0x%08x", display->flags); | ||
2420 | for(size_t layerId=0 ; layerId < display->numHwLayers ; layerId++) { | ||
2421 | hwc_layer_1_t& layer = display->hwLayers[layerId]; | ||
2422 | ALOGV(" Layer[%zu]:", layerId); | ||
2423 | ALOGV(" composition : 0x%08x", layer.compositionType); | ||
2424 | ALOGV(" hints : 0x%08x", layer.hints); | ||
2425 | ALOGV(" flags : 0x%08x", layer.flags); | ||
2426 | ALOGV(" handle : 0x%p", layer.handle); | ||
2427 | ALOGV(" transform : 0x%08x", layer.transform); | ||
2428 | ALOGV(" blending : 0x%08x", layer.blending); | ||
2429 | ALOGV(" sourceCropf : %f, %f, %f, %f", | ||
2430 | layer.sourceCropf.left, | ||
2431 | layer.sourceCropf.top, | ||
2432 | layer.sourceCropf.right, | ||
2433 | layer.sourceCropf.bottom); | ||
2434 | ALOGV(" displayFrame : %d, %d, %d, %d", | ||
2435 | layer.displayFrame.left, | ||
2436 | layer.displayFrame.left, | ||
2437 | layer.displayFrame.left, | ||
2438 | layer.displayFrame.left); | ||
2439 | hwc_region_t& visReg = layer.visibleRegionScreen; | ||
2440 | ALOGV(" visibleRegionScreen: #0x%08zx[@0x%p]", | ||
2441 | visReg.numRects, | ||
2442 | visReg.rects); | ||
2443 | for (size_t visRegId=0; visRegId < visReg.numRects ; visRegId++) { | ||
2444 | if (layer.visibleRegionScreen.rects == nullptr) { | ||
2445 | ALOGV(" null"); | ||
2446 | } else { | ||
2447 | ALOGV(" visibleRegionScreen[%zu] %d, %d, %d, %d", | ||
2448 | visRegId, | ||
2449 | visReg.rects[visRegId].left, | ||
2450 | visReg.rects[visRegId].top, | ||
2451 | visReg.rects[visRegId].right, | ||
2452 | visReg.rects[visRegId].bottom); | ||
2453 | } | ||
2454 | } | ||
2455 | ALOGV(" acquireFenceFd : 0x%08x", layer.acquireFenceFd); | ||
2456 | ALOGV(" releaseFenceFd : 0x%08x", layer.releaseFenceFd); | ||
2457 | ALOGV(" planeAlpha : 0x%08x", layer.planeAlpha); | ||
2458 | if (getMinorVersion(device) < 5) | ||
2459 | continue; | ||
2460 | ALOGV(" surfaceDamage : #0x%08zx[@0x%p]", | ||
2461 | layer.surfaceDamage.numRects, | ||
2462 | layer.surfaceDamage.rects); | ||
2463 | for (size_t sdId=0; sdId < layer.surfaceDamage.numRects ; sdId++) { | ||
2464 | if (layer.surfaceDamage.rects == nullptr) { | ||
2465 | ALOGV(" null"); | ||
2466 | } else { | ||
2467 | ALOGV(" surfaceDamage[%zu] %d, %d, %d, %d", | ||
2468 | sdId, | ||
2469 | layer.surfaceDamage.rects[sdId].left, | ||
2470 | layer.surfaceDamage.rects[sdId].top, | ||
2471 | layer.surfaceDamage.rects[sdId].right, | ||
2472 | layer.surfaceDamage.rects[sdId].bottom); | ||
2473 | } | ||
2474 | } | ||
2475 | } | ||
2476 | displayId++; | ||
2477 | } | ||
2478 | ALOGV("-----------------------------"); | ||
2479 | } | ||
2480 | |||
2481 | Error HWC2On1Adapter::setAllDisplays() { | ||
2482 | ATRACE_CALL(); | ||
2483 | |||
2484 | std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); | ||
2485 | |||
2486 | // Make sure we're ready to validate | ||
2487 | for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) { | ||
2488 | if (mHwc1Contents[hwc1Id] == nullptr) { | ||
2489 | continue; | ||
2490 | } | ||
2491 | |||
2492 | auto displayId = mHwc1DisplayMap[hwc1Id]; | ||
2493 | auto& display = mDisplays[displayId]; | ||
2494 | Error error = display->set(*mHwc1Contents[hwc1Id]); | ||
2495 | if (error != Error::None) { | ||
2496 | ALOGE("setAllDisplays: Failed to set display %zd: %s", hwc1Id, | ||
2497 | to_string(error).c_str()); | ||
2498 | return error; | ||
2499 | } | ||
2500 | } | ||
2501 | |||
2502 | ALOGV("Calling HWC1 set"); | ||
2503 | { | ||
2504 | ATRACE_NAME("HWC1 set"); | ||
2505 | //dumpHWC1Message(mHwc1Device, mHwc1Contents.size(), mHwc1Contents.data()); | ||
2506 | mHwc1Device->set(mHwc1Device, mHwc1Contents.size(), | ||
2507 | mHwc1Contents.data()); | ||
2508 | } | ||
2509 | |||
2510 | // Add retire and release fences | ||
2511 | for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) { | ||
2512 | if (mHwc1Contents[hwc1Id] == nullptr) { | ||
2513 | continue; | ||
2514 | } | ||
2515 | |||
2516 | auto displayId = mHwc1DisplayMap[hwc1Id]; | ||
2517 | auto& display = mDisplays[displayId]; | ||
2518 | auto retireFenceFd = mHwc1Contents[hwc1Id]->retireFenceFd; | ||
2519 | ALOGV("setAllDisplays: Adding retire fence %d to display %zd", | ||
2520 | retireFenceFd, hwc1Id); | ||
2521 | display->addRetireFence(mHwc1Contents[hwc1Id]->retireFenceFd); | ||
2522 | display->addReleaseFences(*mHwc1Contents[hwc1Id]); | ||
2523 | } | ||
2524 | |||
2525 | return Error::None; | ||
2526 | } | ||
2527 | |||
2528 | void HWC2On1Adapter::hwc1Invalidate() { | ||
2529 | ALOGV("Received hwc1Invalidate"); | ||
2530 | |||
2531 | std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); | ||
2532 | |||
2533 | // If the HWC2-side callback hasn't been registered yet, buffer this until | ||
2534 | // it is registered. | ||
2535 | if (mCallbacks.count(Callback::Refresh) == 0) { | ||
2536 | mHasPendingInvalidate = true; | ||
2537 | return; | ||
2538 | } | ||
2539 | |||
2540 | const auto& callbackInfo = mCallbacks[Callback::Refresh]; | ||
2541 | std::vector<hwc2_display_t> displays; | ||
2542 | for (const auto& displayPair : mDisplays) { | ||
2543 | displays.emplace_back(displayPair.first); | ||
2544 | } | ||
2545 | |||
2546 | // Call back without the state lock held. | ||
2547 | lock.unlock(); | ||
2548 | |||
2549 | auto refresh = reinterpret_cast<HWC2_PFN_REFRESH>(callbackInfo.pointer); | ||
2550 | for (auto display : displays) { | ||
2551 | refresh(callbackInfo.data, display); | ||
2552 | } | ||
2553 | } | ||
2554 | |||
2555 | void HWC2On1Adapter::hwc1Vsync(int hwc1DisplayId, int64_t timestamp) { | ||
2556 | ALOGV("Received hwc1Vsync(%d, %" PRId64 ")", hwc1DisplayId, timestamp); | ||
2557 | |||
2558 | std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); | ||
2559 | |||
2560 | // If the HWC2-side callback hasn't been registered yet, buffer this until | ||
2561 | // it is registered. | ||
2562 | if (mCallbacks.count(Callback::Vsync) == 0) { | ||
2563 | mPendingVsyncs.emplace_back(hwc1DisplayId, timestamp); | ||
2564 | return; | ||
2565 | } | ||
2566 | |||
2567 | if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) { | ||
2568 | ALOGE("hwc1Vsync: Couldn't find display for HWC1 id %d", hwc1DisplayId); | ||
2569 | return; | ||
2570 | } | ||
2571 | |||
2572 | const auto& callbackInfo = mCallbacks[Callback::Vsync]; | ||
2573 | auto displayId = mHwc1DisplayMap[hwc1DisplayId]; | ||
2574 | |||
2575 | // Call back without the state lock held. | ||
2576 | lock.unlock(); | ||
2577 | |||
2578 | auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(callbackInfo.pointer); | ||
2579 | vsync(callbackInfo.data, displayId, timestamp); | ||
2580 | } | ||
2581 | |||
2582 | void HWC2On1Adapter::hwc1Hotplug(int hwc1DisplayId, int connected) { | ||
2583 | ALOGV("Received hwc1Hotplug(%d, %d)", hwc1DisplayId, connected); | ||
2584 | |||
2585 | if (hwc1DisplayId != HWC_DISPLAY_EXTERNAL) { | ||
2586 | ALOGE("hwc1Hotplug: Received hotplug for non-external display"); | ||
2587 | return; | ||
2588 | } | ||
2589 | |||
2590 | std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex); | ||
2591 | |||
2592 | // If the HWC2-side callback hasn't been registered yet, buffer this until | ||
2593 | // it is registered | ||
2594 | if (mCallbacks.count(Callback::Hotplug) == 0) { | ||
2595 | mPendingHotplugs.emplace_back(hwc1DisplayId, connected); | ||
2596 | return; | ||
2597 | } | ||
2598 | |||
2599 | hwc2_display_t displayId = UINT64_MAX; | ||
2600 | if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) { | ||
2601 | if (connected == 0) { | ||
2602 | ALOGW("hwc1Hotplug: Received disconnect for unconnected display"); | ||
2603 | return; | ||
2604 | } | ||
2605 | |||
2606 | // Create a new display on connect | ||
2607 | auto display = std::make_shared<HWC2On1Adapter::Display>(*this, | ||
2608 | HWC2::DisplayType::Physical); | ||
2609 | display->setHwc1Id(HWC_DISPLAY_EXTERNAL); | ||
2610 | display->populateConfigs(); | ||
2611 | displayId = display->getId(); | ||
2612 | mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL] = displayId; | ||
2613 | mDisplays.emplace(displayId, std::move(display)); | ||
2614 | } else { | ||
2615 | if (connected != 0) { | ||
2616 | ALOGW("hwc1Hotplug: Received connect for previously connected " | ||
2617 | "display"); | ||
2618 | return; | ||
2619 | } | ||
2620 | |||
2621 | // Disconnect an existing display | ||
2622 | displayId = mHwc1DisplayMap[hwc1DisplayId]; | ||
2623 | mHwc1DisplayMap.erase(HWC_DISPLAY_EXTERNAL); | ||
2624 | mDisplays.erase(displayId); | ||
2625 | } | ||
2626 | |||
2627 | const auto& callbackInfo = mCallbacks[Callback::Hotplug]; | ||
2628 | |||
2629 | // Call back without the state lock held | ||
2630 | lock.unlock(); | ||
2631 | |||
2632 | auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(callbackInfo.pointer); | ||
2633 | auto hwc2Connected = (connected == 0) ? | ||
2634 | HWC2::Connection::Disconnected : HWC2::Connection::Connected; | ||
2635 | hotplug(callbackInfo.data, displayId, static_cast<int32_t>(hwc2Connected)); | ||
2636 | } | ||
2637 | } // namespace android | ||
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/MiniFence.cpp b/graphics/composer/2.1/utils/hwc2on1adapter/MiniFence.cpp new file mode 100644 index 00000000..dfbe4d63 --- /dev/null +++ b/graphics/composer/2.1/utils/hwc2on1adapter/MiniFence.cpp | |||
@@ -0,0 +1,42 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include "hwc2on1adapter/MiniFence.h" | ||
18 | |||
19 | #include <unistd.h> | ||
20 | |||
21 | namespace android { | ||
22 | |||
23 | const sp<MiniFence> MiniFence::NO_FENCE = sp<MiniFence>(new MiniFence); | ||
24 | |||
25 | MiniFence::MiniFence() : | ||
26 | mFenceFd(-1) { | ||
27 | } | ||
28 | |||
29 | MiniFence::MiniFence(int fenceFd) : | ||
30 | mFenceFd(fenceFd) { | ||
31 | } | ||
32 | |||
33 | MiniFence::~MiniFence() { | ||
34 | if (mFenceFd != -1) { | ||
35 | close(mFenceFd); | ||
36 | } | ||
37 | } | ||
38 | |||
39 | int MiniFence::dup() const { | ||
40 | return ::dup(mFenceFd); | ||
41 | } | ||
42 | } | ||
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h new file mode 100644 index 00000000..3badfce0 --- /dev/null +++ b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/HWC2On1Adapter.h | |||
@@ -0,0 +1,738 @@ | |||
1 | /* | ||
2 | * Copyright 2015 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef ANDROID_SF_HWC2_ON_1_ADAPTER_H | ||
18 | #define ANDROID_SF_HWC2_ON_1_ADAPTER_H | ||
19 | |||
20 | #define HWC2_INCLUDE_STRINGIFICATION | ||
21 | #define HWC2_USE_CPP11 | ||
22 | #include <hardware/hwcomposer2.h> | ||
23 | #undef HWC2_INCLUDE_STRINGIFICATION | ||
24 | #undef HWC2_USE_CPP11 | ||
25 | |||
26 | #include "MiniFence.h" | ||
27 | |||
28 | #include <atomic> | ||
29 | #include <map> | ||
30 | #include <mutex> | ||
31 | #include <queue> | ||
32 | #include <set> | ||
33 | #include <unordered_map> | ||
34 | #include <unordered_set> | ||
35 | #include <vector> | ||
36 | |||
37 | struct hwc_composer_device_1; | ||
38 | struct hwc_display_contents_1; | ||
39 | struct hwc_layer_1; | ||
40 | |||
41 | namespace android { | ||
42 | |||
43 | // For devices unable to provide an implementation of HWC2 (see hwcomposer2.h), | ||
44 | // we provide an adapter able to talk to HWC1 (see hwcomposer.h). It translates | ||
45 | // streamed function calls ala HWC2 model to batched array of structs calls ala | ||
46 | // HWC1 model. | ||
47 | class HWC2On1Adapter : public hwc2_device_t | ||
48 | { | ||
49 | public: | ||
50 | explicit HWC2On1Adapter(struct hwc_composer_device_1* hwc1Device); | ||
51 | ~HWC2On1Adapter(); | ||
52 | |||
53 | struct hwc_composer_device_1* getHwc1Device() const { return mHwc1Device; } | ||
54 | uint8_t getHwc1MinorVersion() const { return mHwc1MinorVersion; } | ||
55 | |||
56 | private: | ||
57 | static inline HWC2On1Adapter* getAdapter(hwc2_device_t* device) { | ||
58 | return static_cast<HWC2On1Adapter*>(device); | ||
59 | } | ||
60 | |||
61 | // getCapabilities | ||
62 | |||
63 | void doGetCapabilities(uint32_t* outCount, | ||
64 | int32_t* /*hwc2_capability_t*/ outCapabilities); | ||
65 | static void getCapabilitiesHook(hwc2_device_t* device, uint32_t* outCount, | ||
66 | int32_t* /*hwc2_capability_t*/ outCapabilities) { | ||
67 | getAdapter(device)->doGetCapabilities(outCount, outCapabilities); | ||
68 | } | ||
69 | |||
70 | bool supportsBackgroundColor() { | ||
71 | return mHwc1SupportsBackgroundColor; | ||
72 | } | ||
73 | |||
74 | // getFunction | ||
75 | |||
76 | hwc2_function_pointer_t doGetFunction(HWC2::FunctionDescriptor descriptor); | ||
77 | static hwc2_function_pointer_t getFunctionHook(hwc2_device_t* device, | ||
78 | int32_t intDesc) { | ||
79 | auto descriptor = static_cast<HWC2::FunctionDescriptor>(intDesc); | ||
80 | return getAdapter(device)->doGetFunction(descriptor); | ||
81 | } | ||
82 | |||
83 | // Device functions | ||
84 | |||
85 | HWC2::Error createVirtualDisplay(uint32_t width, uint32_t height, | ||
86 | hwc2_display_t* outDisplay); | ||
87 | static int32_t createVirtualDisplayHook(hwc2_device_t* device, | ||
88 | uint32_t width, uint32_t height, int32_t* /*format*/, | ||
89 | hwc2_display_t* outDisplay) { | ||
90 | // HWC1 implementations cannot override the buffer format requested by | ||
91 | // the consumer | ||
92 | auto error = getAdapter(device)->createVirtualDisplay(width, height, | ||
93 | outDisplay); | ||
94 | return static_cast<int32_t>(error); | ||
95 | } | ||
96 | |||
97 | HWC2::Error destroyVirtualDisplay(hwc2_display_t display); | ||
98 | static int32_t destroyVirtualDisplayHook(hwc2_device_t* device, | ||
99 | hwc2_display_t display) { | ||
100 | auto error = getAdapter(device)->destroyVirtualDisplay(display); | ||
101 | return static_cast<int32_t>(error); | ||
102 | } | ||
103 | |||
104 | std::string mDumpString; | ||
105 | void dump(uint32_t* outSize, char* outBuffer); | ||
106 | static void dumpHook(hwc2_device_t* device, uint32_t* outSize, | ||
107 | char* outBuffer) { | ||
108 | getAdapter(device)->dump(outSize, outBuffer); | ||
109 | } | ||
110 | |||
111 | uint32_t getMaxVirtualDisplayCount(); | ||
112 | static uint32_t getMaxVirtualDisplayCountHook(hwc2_device_t* device) { | ||
113 | return getAdapter(device)->getMaxVirtualDisplayCount(); | ||
114 | } | ||
115 | |||
116 | HWC2::Error registerCallback(HWC2::Callback descriptor, | ||
117 | hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer); | ||
118 | static int32_t registerCallbackHook(hwc2_device_t* device, | ||
119 | int32_t intDesc, hwc2_callback_data_t callbackData, | ||
120 | hwc2_function_pointer_t pointer) { | ||
121 | auto descriptor = static_cast<HWC2::Callback>(intDesc); | ||
122 | auto error = getAdapter(device)->registerCallback(descriptor, | ||
123 | callbackData, pointer); | ||
124 | return static_cast<int32_t>(error); | ||
125 | } | ||
126 | |||
127 | // Display functions | ||
128 | |||
129 | class Layer; | ||
130 | |||
131 | class SortLayersByZ { | ||
132 | public: | ||
133 | bool operator()(const std::shared_ptr<Layer>& lhs, | ||
134 | const std::shared_ptr<Layer>& rhs); | ||
135 | }; | ||
136 | |||
137 | // The semantics of the fences returned by the device differ between | ||
138 | // hwc1.set() and hwc2.present(). Read hwcomposer.h and hwcomposer2.h | ||
139 | // for more information. | ||
140 | // | ||
141 | // Release fences in hwc1 are obtained on set() for a frame n and signaled | ||
142 | // when the layer buffer is not needed for read operations anymore | ||
143 | // (typically on frame n+1). In HWC2, release fences are obtained with a | ||
144 | // special call after present() for frame n. These fences signal | ||
145 | // on frame n: More specifically, the fence for a given buffer provided in | ||
146 | // frame n will signal when the prior buffer is no longer required. | ||
147 | // | ||
148 | // A retire fence (HWC1) is signaled when a composition is replaced | ||
149 | // on the panel whereas a present fence (HWC2) is signaled when a | ||
150 | // composition starts to be displayed on a panel. | ||
151 | // | ||
152 | // The HWC2to1Adapter emulates the new fence semantics for a frame | ||
153 | // n by returning the fence from frame n-1. For frame 0, the adapter | ||
154 | // returns NO_FENCE. | ||
155 | class DeferredFence { | ||
156 | public: | ||
157 | DeferredFence() | ||
158 | : mFences({MiniFence::NO_FENCE, MiniFence::NO_FENCE}) {} | ||
159 | |||
160 | void add(int32_t fenceFd) { | ||
161 | mFences.emplace(new MiniFence(fenceFd)); | ||
162 | mFences.pop(); | ||
163 | } | ||
164 | |||
165 | const sp<MiniFence>& get() const { | ||
166 | return mFences.front(); | ||
167 | } | ||
168 | |||
169 | private: | ||
170 | // There are always two fences in this queue. | ||
171 | std::queue<sp<MiniFence>> mFences; | ||
172 | }; | ||
173 | |||
174 | class FencedBuffer { | ||
175 | public: | ||
176 | FencedBuffer() : mBuffer(nullptr), mFence(MiniFence::NO_FENCE) {} | ||
177 | |||
178 | void setBuffer(buffer_handle_t buffer) { mBuffer = buffer; } | ||
179 | void setFence(int fenceFd) { mFence = new MiniFence(fenceFd); } | ||
180 | |||
181 | buffer_handle_t getBuffer() const { return mBuffer; } | ||
182 | int getFence() const { return mFence->dup(); } | ||
183 | |||
184 | private: | ||
185 | buffer_handle_t mBuffer; | ||
186 | sp<MiniFence> mFence; | ||
187 | }; | ||
188 | |||
189 | class Display { | ||
190 | public: | ||
191 | Display(HWC2On1Adapter& device, HWC2::DisplayType type); | ||
192 | |||
193 | hwc2_display_t getId() const { return mId; } | ||
194 | HWC2On1Adapter& getDevice() const { return mDevice; } | ||
195 | |||
196 | // Does not require locking because it is set before adding the | ||
197 | // Displays to the Adapter's list of displays | ||
198 | void setHwc1Id(int32_t id) { mHwc1Id = id; } | ||
199 | int32_t getHwc1Id() const { return mHwc1Id; } | ||
200 | |||
201 | // HWC2 Display functions | ||
202 | HWC2::Error acceptChanges(); | ||
203 | HWC2::Error createLayer(hwc2_layer_t* outLayerId); | ||
204 | HWC2::Error destroyLayer(hwc2_layer_t layerId); | ||
205 | HWC2::Error getActiveConfig(hwc2_config_t* outConfigId); | ||
206 | HWC2::Error getAttribute(hwc2_config_t configId, | ||
207 | HWC2::Attribute attribute, int32_t* outValue); | ||
208 | HWC2::Error getChangedCompositionTypes(uint32_t* outNumElements, | ||
209 | hwc2_layer_t* outLayers, int32_t* outTypes); | ||
210 | HWC2::Error getColorModes(uint32_t* outNumModes, int32_t* outModes); | ||
211 | HWC2::Error getConfigs(uint32_t* outNumConfigs, | ||
212 | hwc2_config_t* outConfigIds); | ||
213 | HWC2::Error getDozeSupport(int32_t* outSupport); | ||
214 | HWC2::Error getHdrCapabilities(uint32_t* outNumTypes, | ||
215 | int32_t* outTypes, float* outMaxLuminance, | ||
216 | float* outMaxAverageLuminance, float* outMinLuminance); | ||
217 | HWC2::Error getName(uint32_t* outSize, char* outName); | ||
218 | HWC2::Error getReleaseFences(uint32_t* outNumElements, | ||
219 | hwc2_layer_t* outLayers, int32_t* outFences); | ||
220 | HWC2::Error getRequests(int32_t* outDisplayRequests, | ||
221 | uint32_t* outNumElements, hwc2_layer_t* outLayers, | ||
222 | int32_t* outLayerRequests); | ||
223 | HWC2::Error getType(int32_t* outType); | ||
224 | |||
225 | // Since HWC1 "presents" (called "set" in HWC1) all Displays | ||
226 | // at once, the first call to any Display::present will trigger | ||
227 | // present() on all Displays in the Device. Subsequent calls without | ||
228 | // first calling validate() are noop (except for duping/returning | ||
229 | // the retire fence). | ||
230 | HWC2::Error present(int32_t* outRetireFence); | ||
231 | |||
232 | HWC2::Error setActiveConfig(hwc2_config_t configId); | ||
233 | HWC2::Error setClientTarget(buffer_handle_t target, | ||
234 | int32_t acquireFence, int32_t dataspace, | ||
235 | hwc_region_t damage); | ||
236 | HWC2::Error setColorMode(android_color_mode_t mode); | ||
237 | HWC2::Error setColorTransform(android_color_transform_t hint); | ||
238 | HWC2::Error setOutputBuffer(buffer_handle_t buffer, | ||
239 | int32_t releaseFence); | ||
240 | HWC2::Error setPowerMode(HWC2::PowerMode mode); | ||
241 | HWC2::Error setVsyncEnabled(HWC2::Vsync enabled); | ||
242 | |||
243 | // Since HWC1 "validates" (called "prepare" in HWC1) all Displays | ||
244 | // at once, the first call to any Display::validate() will trigger | ||
245 | // validate() on all other Displays in the Device. | ||
246 | HWC2::Error validate(uint32_t* outNumTypes, | ||
247 | uint32_t* outNumRequests); | ||
248 | |||
249 | HWC2::Error updateLayerZ(hwc2_layer_t layerId, uint32_t z); | ||
250 | |||
251 | HWC2::Error getClientTargetSupport(uint32_t width, uint32_t height, | ||
252 | int32_t format, int32_t dataspace); | ||
253 | |||
254 | // Read configs from HWC1 device | ||
255 | void populateConfigs(); | ||
256 | |||
257 | // Set configs for a virtual display | ||
258 | void populateConfigs(uint32_t width, uint32_t height); | ||
259 | |||
260 | bool prepare(); | ||
261 | |||
262 | // Called after hwc.prepare() with responses from the device. | ||
263 | void generateChanges(); | ||
264 | |||
265 | bool hasChanges() const; | ||
266 | HWC2::Error set(hwc_display_contents_1& hwcContents); | ||
267 | void addRetireFence(int fenceFd); | ||
268 | void addReleaseFences(const hwc_display_contents_1& hwcContents); | ||
269 | |||
270 | bool hasColorTransform() const; | ||
271 | |||
272 | std::string dump() const; | ||
273 | |||
274 | // Return a rect from the pool allocated during validate() | ||
275 | hwc_rect_t* GetRects(size_t numRects); | ||
276 | |||
277 | hwc_display_contents_1* getDisplayContents(); | ||
278 | |||
279 | void markGeometryChanged() { mGeometryChanged = true; } | ||
280 | void resetGeometryMarker() { mGeometryChanged = false;} | ||
281 | private: | ||
282 | class Config { | ||
283 | public: | ||
284 | Config(Display& display) | ||
285 | : mDisplay(display), | ||
286 | mId(0), | ||
287 | mAttributes() {} | ||
288 | |||
289 | bool isOnDisplay(const Display& display) const { | ||
290 | return display.getId() == mDisplay.getId(); | ||
291 | } | ||
292 | |||
293 | void setAttribute(HWC2::Attribute attribute, int32_t value); | ||
294 | int32_t getAttribute(HWC2::Attribute attribute) const; | ||
295 | |||
296 | void setHwc1Id(uint32_t id); | ||
297 | bool hasHwc1Id(uint32_t id) const; | ||
298 | HWC2::Error getColorModeForHwc1Id(uint32_t id, | ||
299 | android_color_mode_t *outMode) const; | ||
300 | HWC2::Error getHwc1IdForColorMode(android_color_mode_t mode, | ||
301 | uint32_t* outId) const; | ||
302 | |||
303 | void setId(hwc2_config_t id) { mId = id; } | ||
304 | hwc2_config_t getId() const { return mId; } | ||
305 | |||
306 | // Attempts to merge two configs that differ only in color | ||
307 | // mode. Returns whether the merge was successful | ||
308 | bool merge(const Config& other); | ||
309 | |||
310 | std::set<android_color_mode_t> getColorModes() const; | ||
311 | |||
312 | // splitLine divides the output into two lines suitable for | ||
313 | // dumpsys SurfaceFlinger | ||
314 | std::string toString(bool splitLine = false) const; | ||
315 | |||
316 | private: | ||
317 | Display& mDisplay; | ||
318 | hwc2_config_t mId; | ||
319 | std::unordered_map<HWC2::Attribute, int32_t> mAttributes; | ||
320 | |||
321 | // Maps from color transform to HWC1 config ID | ||
322 | std::unordered_map<android_color_mode_t, uint32_t> mHwc1Ids; | ||
323 | }; | ||
324 | |||
325 | // Stores changes requested from the device upon calling prepare(). | ||
326 | // Handles change request to: | ||
327 | // - Layer composition type. | ||
328 | // - Layer hints. | ||
329 | class Changes { | ||
330 | public: | ||
331 | uint32_t getNumTypes() const { | ||
332 | return static_cast<uint32_t>(mTypeChanges.size()); | ||
333 | } | ||
334 | |||
335 | uint32_t getNumLayerRequests() const { | ||
336 | return static_cast<uint32_t>(mLayerRequests.size()); | ||
337 | } | ||
338 | |||
339 | const std::unordered_map<hwc2_layer_t, HWC2::Composition>& | ||
340 | getTypeChanges() const { | ||
341 | return mTypeChanges; | ||
342 | } | ||
343 | |||
344 | const std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>& | ||
345 | getLayerRequests() const { | ||
346 | return mLayerRequests; | ||
347 | } | ||
348 | |||
349 | void addTypeChange(hwc2_layer_t layerId, | ||
350 | HWC2::Composition type) { | ||
351 | mTypeChanges.insert({layerId, type}); | ||
352 | } | ||
353 | |||
354 | void clearTypeChanges() { mTypeChanges.clear(); } | ||
355 | |||
356 | void addLayerRequest(hwc2_layer_t layerId, | ||
357 | HWC2::LayerRequest request) { | ||
358 | mLayerRequests.insert({layerId, request}); | ||
359 | } | ||
360 | |||
361 | private: | ||
362 | std::unordered_map<hwc2_layer_t, HWC2::Composition> | ||
363 | mTypeChanges; | ||
364 | std::unordered_map<hwc2_layer_t, HWC2::LayerRequest> | ||
365 | mLayerRequests; | ||
366 | }; | ||
367 | |||
368 | std::shared_ptr<const Config> | ||
369 | getConfig(hwc2_config_t configId) const; | ||
370 | |||
371 | void populateColorModes(); | ||
372 | void initializeActiveConfig(); | ||
373 | |||
374 | // Creates a bi-directional mapping between index in HWC1 | ||
375 | // prepare/set array and Layer object. Stores mapping in | ||
376 | // mHwc1LayerMap and also updates Layer's attribute mHwc1Id. | ||
377 | void assignHwc1LayerIds(); | ||
378 | |||
379 | // Called after a response to prepare() has been received: | ||
380 | // Ingest composition type changes requested by the device. | ||
381 | void updateTypeChanges(const struct hwc_layer_1& hwc1Layer, | ||
382 | const Layer& layer); | ||
383 | |||
384 | // Called after a response to prepare() has been received: | ||
385 | // Ingest layer hint changes requested by the device. | ||
386 | void updateLayerRequests(const struct hwc_layer_1& hwc1Layer, | ||
387 | const Layer& layer); | ||
388 | |||
389 | // Set all fields in HWC1 comm array for layer containing the | ||
390 | // HWC_FRAMEBUFFER_TARGET (always the last layer). | ||
391 | void prepareFramebufferTarget(); | ||
392 | |||
393 | // Display ID generator. | ||
394 | static std::atomic<hwc2_display_t> sNextId; | ||
395 | const hwc2_display_t mId; | ||
396 | |||
397 | |||
398 | HWC2On1Adapter& mDevice; | ||
399 | |||
400 | // The state of this display should only be modified from | ||
401 | // SurfaceFlinger's main loop, with the exception of when dump is | ||
402 | // called. To prevent a bad state from crashing us during a dump | ||
403 | // call, all public calls into Display must acquire this mutex. | ||
404 | // | ||
405 | // It is recursive because we don't want to deadlock in validate | ||
406 | // (or present) when we call HWC2On1Adapter::prepareAllDisplays | ||
407 | // (or setAllDisplays), which calls back into Display functions | ||
408 | // which require locking. | ||
409 | mutable std::recursive_mutex mStateMutex; | ||
410 | |||
411 | // Allocate RAM able to store all layers and rects used for | ||
412 | // communication with HWC1. Place allocated RAM in variable | ||
413 | // mHwc1RequestedContents. | ||
414 | void allocateRequestedContents(); | ||
415 | |||
416 | // Array of structs exchanged between client and hwc1 device. | ||
417 | // Sent to device upon calling prepare(). | ||
418 | std::unique_ptr<hwc_display_contents_1> mHwc1RequestedContents; | ||
419 | private: | ||
420 | DeferredFence mRetireFence; | ||
421 | |||
422 | // Will only be non-null after the Display has been validated and | ||
423 | // before it has been presented | ||
424 | std::unique_ptr<Changes> mChanges; | ||
425 | |||
426 | int32_t mHwc1Id; | ||
427 | |||
428 | std::vector<std::shared_ptr<Config>> mConfigs; | ||
429 | std::shared_ptr<const Config> mActiveConfig; | ||
430 | std::set<android_color_mode_t> mColorModes; | ||
431 | android_color_mode_t mActiveColorMode; | ||
432 | std::string mName; | ||
433 | HWC2::DisplayType mType; | ||
434 | HWC2::PowerMode mPowerMode; | ||
435 | HWC2::Vsync mVsyncEnabled; | ||
436 | |||
437 | // Used to populate HWC1 HWC_FRAMEBUFFER_TARGET layer | ||
438 | FencedBuffer mClientTarget; | ||
439 | |||
440 | |||
441 | FencedBuffer mOutputBuffer; | ||
442 | |||
443 | bool mHasColorTransform; | ||
444 | |||
445 | // All layers this Display is aware of. | ||
446 | std::multiset<std::shared_ptr<Layer>, SortLayersByZ> mLayers; | ||
447 | |||
448 | // Mapping between layer index in array of hwc_display_contents_1* | ||
449 | // passed to HWC1 during validate/set and Layer object. | ||
450 | std::unordered_map<size_t, std::shared_ptr<Layer>> mHwc1LayerMap; | ||
451 | |||
452 | // All communication with HWC1 via prepare/set is done with one | ||
453 | // alloc. This pointer is pointing to a pool of hwc_rect_t. | ||
454 | size_t mNumAvailableRects; | ||
455 | hwc_rect_t* mNextAvailableRect; | ||
456 | |||
457 | // True if any of the Layers contained in this Display have been | ||
458 | // updated with anything other than a buffer since last call to | ||
459 | // Display::set() | ||
460 | bool mGeometryChanged; | ||
461 | }; | ||
462 | |||
463 | // Utility template calling a Display object method directly based on the | ||
464 | // hwc2_display_t displayId parameter. | ||
465 | template <typename ...Args> | ||
466 | static int32_t callDisplayFunction(hwc2_device_t* device, | ||
467 | hwc2_display_t displayId, HWC2::Error (Display::*member)(Args...), | ||
468 | Args... args) { | ||
469 | auto display = getAdapter(device)->getDisplay(displayId); | ||
470 | if (!display) { | ||
471 | return static_cast<int32_t>(HWC2::Error::BadDisplay); | ||
472 | } | ||
473 | auto error = ((*display).*member)(std::forward<Args>(args)...); | ||
474 | return static_cast<int32_t>(error); | ||
475 | } | ||
476 | |||
477 | template <typename MF, MF memFunc, typename ...Args> | ||
478 | static int32_t displayHook(hwc2_device_t* device, hwc2_display_t displayId, | ||
479 | Args... args) { | ||
480 | return HWC2On1Adapter::callDisplayFunction(device, displayId, memFunc, | ||
481 | std::forward<Args>(args)...); | ||
482 | } | ||
483 | |||
484 | static int32_t getDisplayAttributeHook(hwc2_device_t* device, | ||
485 | hwc2_display_t display, hwc2_config_t config, | ||
486 | int32_t intAttribute, int32_t* outValue) { | ||
487 | auto attribute = static_cast<HWC2::Attribute>(intAttribute); | ||
488 | return callDisplayFunction(device, display, &Display::getAttribute, | ||
489 | config, attribute, outValue); | ||
490 | } | ||
491 | |||
492 | static int32_t setColorTransformHook(hwc2_device_t* device, | ||
493 | hwc2_display_t display, const float* /*matrix*/, | ||
494 | int32_t /*android_color_transform_t*/ intHint) { | ||
495 | // We intentionally throw away the matrix, because if the hint is | ||
496 | // anything other than IDENTITY, we have to fall back to client | ||
497 | // composition anyway | ||
498 | auto hint = static_cast<android_color_transform_t>(intHint); | ||
499 | return callDisplayFunction(device, display, &Display::setColorTransform, | ||
500 | hint); | ||
501 | } | ||
502 | |||
503 | static int32_t setColorModeHook(hwc2_device_t* device, | ||
504 | hwc2_display_t display, int32_t /*android_color_mode_t*/ intMode) { | ||
505 | auto mode = static_cast<android_color_mode_t>(intMode); | ||
506 | return callDisplayFunction(device, display, &Display::setColorMode, | ||
507 | mode); | ||
508 | } | ||
509 | |||
510 | static int32_t setPowerModeHook(hwc2_device_t* device, | ||
511 | hwc2_display_t display, int32_t intMode) { | ||
512 | auto mode = static_cast<HWC2::PowerMode>(intMode); | ||
513 | return callDisplayFunction(device, display, &Display::setPowerMode, | ||
514 | mode); | ||
515 | } | ||
516 | |||
517 | static int32_t setVsyncEnabledHook(hwc2_device_t* device, | ||
518 | hwc2_display_t display, int32_t intEnabled) { | ||
519 | auto enabled = static_cast<HWC2::Vsync>(intEnabled); | ||
520 | return callDisplayFunction(device, display, &Display::setVsyncEnabled, | ||
521 | enabled); | ||
522 | } | ||
523 | |||
524 | class Layer { | ||
525 | public: | ||
526 | explicit Layer(Display& display); | ||
527 | |||
528 | bool operator==(const Layer& other) { return mId == other.mId; } | ||
529 | bool operator!=(const Layer& other) { return !(*this == other); } | ||
530 | |||
531 | hwc2_layer_t getId() const { return mId; } | ||
532 | Display& getDisplay() const { return mDisplay; } | ||
533 | |||
534 | // HWC2 Layer functions | ||
535 | HWC2::Error setBuffer(buffer_handle_t buffer, int32_t acquireFence); | ||
536 | HWC2::Error setCursorPosition(int32_t x, int32_t y); | ||
537 | HWC2::Error setSurfaceDamage(hwc_region_t damage); | ||
538 | |||
539 | // HWC2 Layer state functions | ||
540 | HWC2::Error setBlendMode(HWC2::BlendMode mode); | ||
541 | HWC2::Error setColor(hwc_color_t color); | ||
542 | HWC2::Error setCompositionType(HWC2::Composition type); | ||
543 | HWC2::Error setDataspace(android_dataspace_t dataspace); | ||
544 | HWC2::Error setDisplayFrame(hwc_rect_t frame); | ||
545 | HWC2::Error setPlaneAlpha(float alpha); | ||
546 | HWC2::Error setSidebandStream(const native_handle_t* stream); | ||
547 | HWC2::Error setSourceCrop(hwc_frect_t crop); | ||
548 | HWC2::Error setTransform(HWC2::Transform transform); | ||
549 | HWC2::Error setVisibleRegion(hwc_region_t visible); | ||
550 | HWC2::Error setZ(uint32_t z); | ||
551 | |||
552 | HWC2::Composition getCompositionType() const { | ||
553 | return mCompositionType; | ||
554 | } | ||
555 | uint32_t getZ() const { return mZ; } | ||
556 | |||
557 | void addReleaseFence(int fenceFd); | ||
558 | const sp<MiniFence>& getReleaseFence() const; | ||
559 | |||
560 | void setHwc1Id(size_t id) { mHwc1Id = id; } | ||
561 | size_t getHwc1Id() const { return mHwc1Id; } | ||
562 | |||
563 | // Write state to HWC1 communication struct. | ||
564 | void applyState(struct hwc_layer_1& hwc1Layer); | ||
565 | |||
566 | std::string dump() const; | ||
567 | |||
568 | std::size_t getNumVisibleRegions() { return mVisibleRegion.size(); } | ||
569 | |||
570 | std::size_t getNumSurfaceDamages() { return mSurfaceDamage.size(); } | ||
571 | |||
572 | // True if a layer cannot be properly rendered by the device due | ||
573 | // to usage of SolidColor (a.k.a BackgroundColor in HWC1). | ||
574 | bool hasUnsupportedBackgroundColor() { | ||
575 | return (mCompositionType == HWC2::Composition::SolidColor && | ||
576 | !mDisplay.getDevice().supportsBackgroundColor()); | ||
577 | } | ||
578 | private: | ||
579 | void applyCommonState(struct hwc_layer_1& hwc1Layer); | ||
580 | void applySolidColorState(struct hwc_layer_1& hwc1Layer); | ||
581 | void applySidebandState(struct hwc_layer_1& hwc1Layer); | ||
582 | void applyBufferState(struct hwc_layer_1& hwc1Layer); | ||
583 | void applyCompositionType(struct hwc_layer_1& hwc1Layer); | ||
584 | |||
585 | static std::atomic<hwc2_layer_t> sNextId; | ||
586 | const hwc2_layer_t mId; | ||
587 | Display& mDisplay; | ||
588 | |||
589 | FencedBuffer mBuffer; | ||
590 | std::vector<hwc_rect_t> mSurfaceDamage; | ||
591 | |||
592 | HWC2::BlendMode mBlendMode; | ||
593 | hwc_color_t mColor; | ||
594 | HWC2::Composition mCompositionType; | ||
595 | hwc_rect_t mDisplayFrame; | ||
596 | float mPlaneAlpha; | ||
597 | const native_handle_t* mSidebandStream; | ||
598 | hwc_frect_t mSourceCrop; | ||
599 | HWC2::Transform mTransform; | ||
600 | std::vector<hwc_rect_t> mVisibleRegion; | ||
601 | |||
602 | uint32_t mZ; | ||
603 | |||
604 | DeferredFence mReleaseFence; | ||
605 | |||
606 | size_t mHwc1Id; | ||
607 | bool mHasUnsupportedPlaneAlpha; | ||
608 | }; | ||
609 | |||
610 | // Utility tempate calling a Layer object method based on ID parameters: | ||
611 | // hwc2_display_t displayId | ||
612 | // and | ||
613 | // hwc2_layer_t layerId | ||
614 | template <typename ...Args> | ||
615 | static int32_t callLayerFunction(hwc2_device_t* device, | ||
616 | hwc2_display_t displayId, hwc2_layer_t layerId, | ||
617 | HWC2::Error (Layer::*member)(Args...), Args... args) { | ||
618 | auto result = getAdapter(device)->getLayer(displayId, layerId); | ||
619 | auto error = std::get<HWC2::Error>(result); | ||
620 | if (error == HWC2::Error::None) { | ||
621 | auto layer = std::get<Layer*>(result); | ||
622 | error = ((*layer).*member)(std::forward<Args>(args)...); | ||
623 | } | ||
624 | return static_cast<int32_t>(error); | ||
625 | } | ||
626 | |||
627 | template <typename MF, MF memFunc, typename ...Args> | ||
628 | static int32_t layerHook(hwc2_device_t* device, hwc2_display_t displayId, | ||
629 | hwc2_layer_t layerId, Args... args) { | ||
630 | return HWC2On1Adapter::callLayerFunction(device, displayId, layerId, | ||
631 | memFunc, std::forward<Args>(args)...); | ||
632 | } | ||
633 | |||
634 | // Layer state functions | ||
635 | |||
636 | static int32_t setLayerBlendModeHook(hwc2_device_t* device, | ||
637 | hwc2_display_t display, hwc2_layer_t layer, int32_t intMode) { | ||
638 | auto mode = static_cast<HWC2::BlendMode>(intMode); | ||
639 | return callLayerFunction(device, display, layer, | ||
640 | &Layer::setBlendMode, mode); | ||
641 | } | ||
642 | |||
643 | static int32_t setLayerCompositionTypeHook(hwc2_device_t* device, | ||
644 | hwc2_display_t display, hwc2_layer_t layer, int32_t intType) { | ||
645 | auto type = static_cast<HWC2::Composition>(intType); | ||
646 | return callLayerFunction(device, display, layer, | ||
647 | &Layer::setCompositionType, type); | ||
648 | } | ||
649 | |||
650 | static int32_t setLayerDataspaceHook(hwc2_device_t* device, | ||
651 | hwc2_display_t display, hwc2_layer_t layer, int32_t intDataspace) { | ||
652 | auto dataspace = static_cast<android_dataspace_t>(intDataspace); | ||
653 | return callLayerFunction(device, display, layer, &Layer::setDataspace, | ||
654 | dataspace); | ||
655 | } | ||
656 | |||
657 | static int32_t setLayerTransformHook(hwc2_device_t* device, | ||
658 | hwc2_display_t display, hwc2_layer_t layer, int32_t intTransform) { | ||
659 | auto transform = static_cast<HWC2::Transform>(intTransform); | ||
660 | return callLayerFunction(device, display, layer, &Layer::setTransform, | ||
661 | transform); | ||
662 | } | ||
663 | |||
664 | static int32_t setLayerZOrderHook(hwc2_device_t* device, | ||
665 | hwc2_display_t display, hwc2_layer_t layer, uint32_t z) { | ||
666 | return callDisplayFunction(device, display, &Display::updateLayerZ, | ||
667 | layer, z); | ||
668 | } | ||
669 | |||
670 | // Adapter internals | ||
671 | |||
672 | void populateCapabilities(); | ||
673 | Display* getDisplay(hwc2_display_t id); | ||
674 | std::tuple<Layer*, HWC2::Error> getLayer(hwc2_display_t displayId, | ||
675 | hwc2_layer_t layerId); | ||
676 | void populatePrimary(); | ||
677 | |||
678 | bool prepareAllDisplays(); | ||
679 | std::vector<struct hwc_display_contents_1*> mHwc1Contents; | ||
680 | HWC2::Error setAllDisplays(); | ||
681 | |||
682 | // Callbacks | ||
683 | void hwc1Invalidate(); | ||
684 | void hwc1Vsync(int hwc1DisplayId, int64_t timestamp); | ||
685 | void hwc1Hotplug(int hwc1DisplayId, int connected); | ||
686 | |||
687 | // These are set in the constructor and before any asynchronous events are | ||
688 | // possible | ||
689 | |||
690 | struct hwc_composer_device_1* const mHwc1Device; | ||
691 | const uint8_t mHwc1MinorVersion; | ||
692 | bool mHwc1SupportsVirtualDisplays; | ||
693 | bool mHwc1SupportsBackgroundColor; | ||
694 | |||
695 | class Callbacks; | ||
696 | const std::unique_ptr<Callbacks> mHwc1Callbacks; | ||
697 | |||
698 | std::unordered_set<HWC2::Capability> mCapabilities; | ||
699 | |||
700 | // These are only accessed from the main SurfaceFlinger thread (not from | ||
701 | // callbacks or dump | ||
702 | |||
703 | std::map<hwc2_layer_t, std::shared_ptr<Layer>> mLayers; | ||
704 | |||
705 | // A HWC1 supports only one virtual display. | ||
706 | std::shared_ptr<Display> mHwc1VirtualDisplay; | ||
707 | |||
708 | // These are potentially accessed from multiple threads, and are protected | ||
709 | // by this mutex. This needs to be recursive, since the HWC1 implementation | ||
710 | // can call back into the invalidate callback on the same thread that is | ||
711 | // calling prepare. | ||
712 | std::recursive_timed_mutex mStateMutex; | ||
713 | |||
714 | struct CallbackInfo { | ||
715 | hwc2_callback_data_t data; | ||
716 | hwc2_function_pointer_t pointer; | ||
717 | }; | ||
718 | std::unordered_map<HWC2::Callback, CallbackInfo> mCallbacks; | ||
719 | bool mHasPendingInvalidate; | ||
720 | |||
721 | // There is a small gap between the time the HWC1 module is started and | ||
722 | // when the callbacks for vsync and hotplugs are registered by the | ||
723 | // HWC2on1Adapter. To prevent losing events they are stored in these arrays | ||
724 | // and fed to the callback as soon as possible. | ||
725 | std::vector<std::pair<int, int64_t>> mPendingVsyncs; | ||
726 | std::vector<std::pair<int, int>> mPendingHotplugs; | ||
727 | |||
728 | // Mapping between HWC1 display id and Display objects. | ||
729 | std::map<hwc2_display_t, std::shared_ptr<Display>> mDisplays; | ||
730 | |||
731 | // Map HWC1 display type (HWC_DISPLAY_PRIMARY, HWC_DISPLAY_EXTERNAL, | ||
732 | // HWC_DISPLAY_VIRTUAL) to Display IDs generated by HWC2on1Adapter objects. | ||
733 | std::unordered_map<int, hwc2_display_t> mHwc1DisplayMap; | ||
734 | }; | ||
735 | |||
736 | } // namespace android | ||
737 | |||
738 | #endif | ||
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/MiniFence.h b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/MiniFence.h new file mode 100644 index 00000000..75de764d --- /dev/null +++ b/graphics/composer/2.1/utils/hwc2on1adapter/include/hwc2on1adapter/MiniFence.h | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef MINIFENCE_H | ||
18 | #define MINIFENCE_H | ||
19 | |||
20 | #include <utils/RefBase.h> | ||
21 | |||
22 | namespace android { | ||
23 | |||
24 | /* MiniFence is a minimal re-implementation of Fence from libui. It exists to | ||
25 | * avoid linking the HWC2on1Adapter to libui and satisfy Treble requirements. | ||
26 | */ | ||
27 | class MiniFence : public LightRefBase<MiniFence> { | ||
28 | public: | ||
29 | static const sp<MiniFence> NO_FENCE; | ||
30 | |||
31 | // Construct a new MiniFence object with an invalid file descriptor. | ||
32 | MiniFence(); | ||
33 | |||
34 | // Construct a new MiniFence object to manage a given fence file descriptor. | ||
35 | // When the new MiniFence object is destructed the file descriptor will be | ||
36 | // closed. | ||
37 | explicit MiniFence(int fenceFd); | ||
38 | |||
39 | // Not copyable or movable. | ||
40 | MiniFence(const MiniFence& rhs) = delete; | ||
41 | MiniFence& operator=(const MiniFence& rhs) = delete; | ||
42 | MiniFence(MiniFence&& rhs) = delete; | ||
43 | MiniFence& operator=(MiniFence&& rhs) = delete; | ||
44 | |||
45 | // Return a duplicate of the fence file descriptor. The caller is | ||
46 | // responsible for closing the returned file descriptor. On error, -1 will | ||
47 | // be returned and errno will indicate the problem. | ||
48 | int dup() const; | ||
49 | |||
50 | private: | ||
51 | // Only allow instantiation using ref counting. | ||
52 | friend class LightRefBase<MiniFence>; | ||
53 | ~MiniFence(); | ||
54 | |||
55 | int mFenceFd; | ||
56 | |||
57 | }; | ||
58 | } | ||
59 | #endif //MINIFENCE_H | ||
diff --git a/graphics/composer/2.1/utils/hwc2onfbadapter/Android.bp b/graphics/composer/2.1/utils/hwc2onfbadapter/Android.bp new file mode 100644 index 00000000..73a41f7f --- /dev/null +++ b/graphics/composer/2.1/utils/hwc2onfbadapter/Android.bp | |||
@@ -0,0 +1,33 @@ | |||
1 | // Copyright 2010 The Android Open Source Project | ||
2 | // | ||
3 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
4 | // you may not use this file except in compliance with the License. | ||
5 | // You may obtain a copy of the License at | ||
6 | // | ||
7 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
8 | // | ||
9 | // Unless required by applicable law or agreed to in writing, software | ||
10 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
12 | // See the License for the specific language governing permissions and | ||
13 | // limitations under the License. | ||
14 | |||
15 | cc_library_shared { | ||
16 | name: "libhwc2onfbadapter", | ||
17 | vendor: true, | ||
18 | |||
19 | clang: true, | ||
20 | cflags: [ | ||
21 | "-Wall", | ||
22 | "-Wextra", | ||
23 | "-Werror", | ||
24 | ], | ||
25 | |||
26 | srcs: [ | ||
27 | "HWC2OnFbAdapter.cpp", | ||
28 | ], | ||
29 | |||
30 | header_libs: ["libhardware_headers"], | ||
31 | shared_libs: ["liblog", "libsync"], | ||
32 | export_include_dirs: ["include"], | ||
33 | } | ||
diff --git a/graphics/composer/2.1/utils/hwc2onfbadapter/HWC2OnFbAdapter.cpp b/graphics/composer/2.1/utils/hwc2onfbadapter/HWC2OnFbAdapter.cpp new file mode 100644 index 00000000..7c9e6518 --- /dev/null +++ b/graphics/composer/2.1/utils/hwc2onfbadapter/HWC2OnFbAdapter.cpp | |||
@@ -0,0 +1,887 @@ | |||
1 | /* | ||
2 | * Copyright 2017 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #define LOG_TAG "HWC2OnFbAdapter" | ||
18 | |||
19 | //#define LOG_NDEBUG 0 | ||
20 | |||
21 | #include "hwc2onfbadapter/HWC2OnFbAdapter.h" | ||
22 | |||
23 | #include <algorithm> | ||
24 | #include <type_traits> | ||
25 | |||
26 | #include <inttypes.h> | ||
27 | #include <time.h> | ||
28 | #include <sys/prctl.h> | ||
29 | #include <unistd.h> // for close | ||
30 | |||
31 | #include <hardware/fb.h> | ||
32 | #include <log/log.h> | ||
33 | #include <sync/sync.h> | ||
34 | |||
35 | namespace android { | ||
36 | |||
37 | namespace { | ||
38 | |||
39 | void dumpHook(hwc2_device_t* device, uint32_t* outSize, char* outBuffer) { | ||
40 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
41 | if (outBuffer) { | ||
42 | *outSize = adapter.getDebugString().copy(outBuffer, *outSize); | ||
43 | } else { | ||
44 | adapter.updateDebugString(); | ||
45 | *outSize = adapter.getDebugString().size(); | ||
46 | } | ||
47 | } | ||
48 | |||
49 | int32_t registerCallbackHook(hwc2_device_t* device, int32_t descriptor, | ||
50 | hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer) { | ||
51 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
52 | switch (descriptor) { | ||
53 | case HWC2_CALLBACK_HOTPLUG: | ||
54 | if (pointer) { | ||
55 | reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer)(callbackData, adapter.getDisplayId(), | ||
56 | HWC2_CONNECTION_CONNECTED); | ||
57 | } | ||
58 | break; | ||
59 | case HWC2_CALLBACK_REFRESH: | ||
60 | break; | ||
61 | case HWC2_CALLBACK_VSYNC: | ||
62 | adapter.setVsyncCallback(reinterpret_cast<HWC2_PFN_VSYNC>(pointer), callbackData); | ||
63 | break; | ||
64 | default: | ||
65 | return HWC2_ERROR_BAD_PARAMETER; | ||
66 | } | ||
67 | |||
68 | return HWC2_ERROR_NONE; | ||
69 | } | ||
70 | |||
71 | uint32_t getMaxVirtualDisplayCountHook(hwc2_device_t* /*device*/) { | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | int32_t createVirtualDisplayHook(hwc2_device_t* /*device*/, uint32_t /*width*/, uint32_t /*height*/, | ||
76 | int32_t* /*format*/, hwc2_display_t* /*outDisplay*/) { | ||
77 | return HWC2_ERROR_NO_RESOURCES; | ||
78 | } | ||
79 | |||
80 | int32_t destroyVirtualDisplayHook(hwc2_device_t* /*device*/, hwc2_display_t /*display*/) { | ||
81 | return HWC2_ERROR_BAD_DISPLAY; | ||
82 | } | ||
83 | |||
84 | int32_t setOutputBufferHook(hwc2_device_t* /*device*/, hwc2_display_t /*display*/, | ||
85 | buffer_handle_t /*buffer*/, int32_t /*releaseFence*/) { | ||
86 | return HWC2_ERROR_BAD_DISPLAY; | ||
87 | } | ||
88 | |||
89 | int32_t getDisplayNameHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outSize, | ||
90 | char* outName) { | ||
91 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
92 | if (adapter.getDisplayId() != display) { | ||
93 | return HWC2_ERROR_BAD_DISPLAY; | ||
94 | } | ||
95 | |||
96 | const auto& info = adapter.getInfo(); | ||
97 | if (outName) { | ||
98 | *outSize = info.name.copy(outName, *outSize); | ||
99 | } else { | ||
100 | *outSize = info.name.size(); | ||
101 | } | ||
102 | |||
103 | return HWC2_ERROR_NONE; | ||
104 | } | ||
105 | |||
106 | int32_t getDisplayTypeHook(hwc2_device_t* device, hwc2_display_t display, int32_t* outType) { | ||
107 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
108 | if (adapter.getDisplayId() != display) { | ||
109 | return HWC2_ERROR_BAD_DISPLAY; | ||
110 | } | ||
111 | |||
112 | *outType = HWC2_DISPLAY_TYPE_PHYSICAL; | ||
113 | return HWC2_ERROR_NONE; | ||
114 | } | ||
115 | |||
116 | int32_t getDozeSupportHook(hwc2_device_t* device, hwc2_display_t display, int32_t* outSupport) { | ||
117 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
118 | if (adapter.getDisplayId() != display) { | ||
119 | return HWC2_ERROR_BAD_DISPLAY; | ||
120 | } | ||
121 | |||
122 | *outSupport = 0; | ||
123 | return HWC2_ERROR_NONE; | ||
124 | } | ||
125 | |||
126 | int32_t getHdrCapabilitiesHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumTypes, | ||
127 | int32_t* /*outTypes*/, float* /*outMaxLuminance*/, | ||
128 | float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/) { | ||
129 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
130 | if (adapter.getDisplayId() != display) { | ||
131 | return HWC2_ERROR_BAD_DISPLAY; | ||
132 | } | ||
133 | |||
134 | *outNumTypes = 0; | ||
135 | return HWC2_ERROR_NONE; | ||
136 | } | ||
137 | |||
138 | int32_t setPowerModeHook(hwc2_device_t* device, hwc2_display_t display, int32_t /*mode*/) { | ||
139 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
140 | if (adapter.getDisplayId() != display) { | ||
141 | return HWC2_ERROR_BAD_DISPLAY; | ||
142 | } | ||
143 | |||
144 | // pretend that it works | ||
145 | return HWC2_ERROR_NONE; | ||
146 | } | ||
147 | |||
148 | int32_t setVsyncEnabledHook(hwc2_device_t* device, hwc2_display_t display, int32_t enabled) { | ||
149 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
150 | if (adapter.getDisplayId() != display) { | ||
151 | return HWC2_ERROR_BAD_DISPLAY; | ||
152 | } | ||
153 | |||
154 | adapter.enableVsync(enabled == HWC2_VSYNC_ENABLE); | ||
155 | return HWC2_ERROR_NONE; | ||
156 | } | ||
157 | |||
158 | int32_t getColorModesHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumModes, | ||
159 | int32_t* outModes) { | ||
160 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
161 | if (adapter.getDisplayId() != display) { | ||
162 | return HWC2_ERROR_BAD_DISPLAY; | ||
163 | } | ||
164 | |||
165 | if (outModes) { | ||
166 | if (*outNumModes > 0) { | ||
167 | outModes[0] = HAL_COLOR_MODE_NATIVE; | ||
168 | *outNumModes = 1; | ||
169 | } | ||
170 | } else { | ||
171 | *outNumModes = 1; | ||
172 | } | ||
173 | |||
174 | return HWC2_ERROR_NONE; | ||
175 | } | ||
176 | |||
177 | int32_t setColorModeHook(hwc2_device_t* device, hwc2_display_t display, int32_t mode) { | ||
178 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
179 | if (adapter.getDisplayId() != display) { | ||
180 | return HWC2_ERROR_BAD_DISPLAY; | ||
181 | } | ||
182 | if (mode != HAL_COLOR_MODE_NATIVE) { | ||
183 | return HWC2_ERROR_BAD_PARAMETER; | ||
184 | } | ||
185 | |||
186 | return HWC2_ERROR_NONE; | ||
187 | } | ||
188 | |||
189 | int32_t setColorTransformHook(hwc2_device_t* device, hwc2_display_t display, | ||
190 | const float* /*matrix*/, int32_t /*hint*/) { | ||
191 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
192 | if (adapter.getDisplayId() != display) { | ||
193 | return HWC2_ERROR_BAD_DISPLAY; | ||
194 | } | ||
195 | |||
196 | // we always force client composition | ||
197 | adapter.setState(HWC2OnFbAdapter::State::MODIFIED); | ||
198 | return HWC2_ERROR_NONE; | ||
199 | } | ||
200 | |||
201 | int32_t getClientTargetSupportHook(hwc2_device_t* device, hwc2_display_t display, uint32_t width, | ||
202 | uint32_t height, int32_t format, int32_t dataspace) { | ||
203 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
204 | if (adapter.getDisplayId() != display) { | ||
205 | return HWC2_ERROR_BAD_DISPLAY; | ||
206 | } | ||
207 | if (dataspace != HAL_DATASPACE_UNKNOWN) { | ||
208 | return HWC2_ERROR_UNSUPPORTED; | ||
209 | } | ||
210 | |||
211 | const auto& info = adapter.getInfo(); | ||
212 | return (info.width == width && info.height == height && info.format == format) | ||
213 | ? HWC2_ERROR_NONE | ||
214 | : HWC2_ERROR_UNSUPPORTED; | ||
215 | } | ||
216 | |||
217 | int32_t setClientTargetHook(hwc2_device_t* device, hwc2_display_t display, buffer_handle_t target, | ||
218 | int32_t acquireFence, int32_t dataspace, hwc_region_t /*damage*/) { | ||
219 | if (acquireFence >= 0) { | ||
220 | sync_wait(acquireFence, -1); | ||
221 | close(acquireFence); | ||
222 | } | ||
223 | |||
224 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
225 | if (adapter.getDisplayId() != display) { | ||
226 | return HWC2_ERROR_BAD_DISPLAY; | ||
227 | } | ||
228 | if (dataspace != HAL_DATASPACE_UNKNOWN) { | ||
229 | return HWC2_ERROR_BAD_PARAMETER; | ||
230 | } | ||
231 | |||
232 | // no state change | ||
233 | adapter.setBuffer(target); | ||
234 | return HWC2_ERROR_NONE; | ||
235 | } | ||
236 | |||
237 | int32_t getDisplayConfigsHook(hwc2_device_t* device, hwc2_display_t display, | ||
238 | uint32_t* outNumConfigs, hwc2_config_t* outConfigs) { | ||
239 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
240 | if (adapter.getDisplayId() != display) { | ||
241 | return HWC2_ERROR_BAD_DISPLAY; | ||
242 | } | ||
243 | |||
244 | if (outConfigs) { | ||
245 | if (*outNumConfigs > 0) { | ||
246 | outConfigs[0] = adapter.getConfigId(); | ||
247 | *outNumConfigs = 1; | ||
248 | } | ||
249 | } else { | ||
250 | *outNumConfigs = 1; | ||
251 | } | ||
252 | |||
253 | return HWC2_ERROR_NONE; | ||
254 | } | ||
255 | |||
256 | int32_t getDisplayAttributeHook(hwc2_device_t* device, hwc2_display_t display, hwc2_config_t config, | ||
257 | int32_t attribute, int32_t* outValue) { | ||
258 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
259 | if (adapter.getDisplayId() != display) { | ||
260 | return HWC2_ERROR_BAD_DISPLAY; | ||
261 | } | ||
262 | if (adapter.getConfigId() != config) { | ||
263 | return HWC2_ERROR_BAD_CONFIG; | ||
264 | } | ||
265 | |||
266 | const auto& info = adapter.getInfo(); | ||
267 | switch (attribute) { | ||
268 | case HWC2_ATTRIBUTE_WIDTH: | ||
269 | *outValue = int32_t(info.width); | ||
270 | break; | ||
271 | case HWC2_ATTRIBUTE_HEIGHT: | ||
272 | *outValue = int32_t(info.height); | ||
273 | break; | ||
274 | case HWC2_ATTRIBUTE_VSYNC_PERIOD: | ||
275 | *outValue = int32_t(info.vsync_period_ns); | ||
276 | break; | ||
277 | case HWC2_ATTRIBUTE_DPI_X: | ||
278 | *outValue = int32_t(info.xdpi_scaled); | ||
279 | break; | ||
280 | case HWC2_ATTRIBUTE_DPI_Y: | ||
281 | *outValue = int32_t(info.ydpi_scaled); | ||
282 | break; | ||
283 | default: | ||
284 | return HWC2_ERROR_BAD_PARAMETER; | ||
285 | } | ||
286 | |||
287 | return HWC2_ERROR_NONE; | ||
288 | } | ||
289 | |||
290 | int32_t getActiveConfigHook(hwc2_device_t* device, hwc2_display_t display, | ||
291 | hwc2_config_t* outConfig) { | ||
292 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
293 | if (adapter.getDisplayId() != display) { | ||
294 | return HWC2_ERROR_BAD_DISPLAY; | ||
295 | } | ||
296 | |||
297 | *outConfig = adapter.getConfigId(); | ||
298 | return HWC2_ERROR_NONE; | ||
299 | } | ||
300 | |||
301 | int32_t setActiveConfigHook(hwc2_device_t* device, hwc2_display_t display, hwc2_config_t config) { | ||
302 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
303 | if (adapter.getDisplayId() != display) { | ||
304 | return HWC2_ERROR_BAD_DISPLAY; | ||
305 | } | ||
306 | if (adapter.getConfigId() != config) { | ||
307 | return HWC2_ERROR_BAD_CONFIG; | ||
308 | } | ||
309 | |||
310 | return HWC2_ERROR_NONE; | ||
311 | } | ||
312 | |||
313 | int32_t validateDisplayHook(hwc2_device_t* device, hwc2_display_t display, uint32_t* outNumTypes, | ||
314 | uint32_t* outNumRequests) { | ||
315 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
316 | if (adapter.getDisplayId() != display) { | ||
317 | return HWC2_ERROR_BAD_DISPLAY; | ||
318 | } | ||
319 | |||
320 | const auto& dirtyLayers = adapter.getDirtyLayers(); | ||
321 | *outNumTypes = dirtyLayers.size(); | ||
322 | *outNumRequests = 0; | ||
323 | |||
324 | if (*outNumTypes > 0) { | ||
325 | adapter.setState(HWC2OnFbAdapter::State::VALIDATED_WITH_CHANGES); | ||
326 | return HWC2_ERROR_HAS_CHANGES; | ||
327 | } else { | ||
328 | adapter.setState(HWC2OnFbAdapter::State::VALIDATED); | ||
329 | return HWC2_ERROR_NONE; | ||
330 | } | ||
331 | } | ||
332 | |||
333 | int32_t getChangedCompositionTypesHook(hwc2_device_t* device, hwc2_display_t display, | ||
334 | uint32_t* outNumElements, hwc2_layer_t* outLayers, | ||
335 | int32_t* outTypes) { | ||
336 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
337 | if (adapter.getDisplayId() != display) { | ||
338 | return HWC2_ERROR_BAD_DISPLAY; | ||
339 | } | ||
340 | if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) { | ||
341 | return HWC2_ERROR_NOT_VALIDATED; | ||
342 | } | ||
343 | |||
344 | // request client composition for all layers | ||
345 | const auto& dirtyLayers = adapter.getDirtyLayers(); | ||
346 | if (outLayers && outTypes) { | ||
347 | *outNumElements = std::min(*outNumElements, uint32_t(dirtyLayers.size())); | ||
348 | auto iter = dirtyLayers.cbegin(); | ||
349 | for (uint32_t i = 0; i < *outNumElements; i++) { | ||
350 | outLayers[i] = *iter++; | ||
351 | outTypes[i] = HWC2_COMPOSITION_CLIENT; | ||
352 | } | ||
353 | } else { | ||
354 | *outNumElements = dirtyLayers.size(); | ||
355 | } | ||
356 | |||
357 | return HWC2_ERROR_NONE; | ||
358 | } | ||
359 | |||
360 | int32_t getDisplayRequestsHook(hwc2_device_t* device, hwc2_display_t display, | ||
361 | int32_t* outDisplayRequests, uint32_t* outNumElements, | ||
362 | hwc2_layer_t* /*outLayers*/, int32_t* /*outLayerRequests*/) { | ||
363 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
364 | if (adapter.getDisplayId() != display) { | ||
365 | return HWC2_ERROR_BAD_DISPLAY; | ||
366 | } | ||
367 | if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) { | ||
368 | return HWC2_ERROR_NOT_VALIDATED; | ||
369 | } | ||
370 | |||
371 | *outDisplayRequests = 0; | ||
372 | *outNumElements = 0; | ||
373 | return HWC2_ERROR_NONE; | ||
374 | } | ||
375 | |||
376 | int32_t acceptDisplayChangesHook(hwc2_device_t* device, hwc2_display_t display) { | ||
377 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
378 | if (adapter.getDisplayId() != display) { | ||
379 | return HWC2_ERROR_BAD_DISPLAY; | ||
380 | } | ||
381 | if (adapter.getState() == HWC2OnFbAdapter::State::MODIFIED) { | ||
382 | return HWC2_ERROR_NOT_VALIDATED; | ||
383 | } | ||
384 | |||
385 | adapter.clearDirtyLayers(); | ||
386 | adapter.setState(HWC2OnFbAdapter::State::VALIDATED); | ||
387 | return HWC2_ERROR_NONE; | ||
388 | } | ||
389 | |||
390 | int32_t presentDisplayHook(hwc2_device_t* device, hwc2_display_t display, | ||
391 | int32_t* outPresentFence) { | ||
392 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
393 | if (adapter.getDisplayId() != display) { | ||
394 | return HWC2_ERROR_BAD_DISPLAY; | ||
395 | } | ||
396 | if (adapter.getState() != HWC2OnFbAdapter::State::VALIDATED) { | ||
397 | return HWC2_ERROR_NOT_VALIDATED; | ||
398 | } | ||
399 | |||
400 | adapter.postBuffer(); | ||
401 | *outPresentFence = -1; | ||
402 | |||
403 | return HWC2_ERROR_NONE; | ||
404 | } | ||
405 | |||
406 | int32_t getReleaseFencesHook(hwc2_device_t* device, hwc2_display_t display, | ||
407 | uint32_t* outNumElements, hwc2_layer_t* /*outLayers*/, | ||
408 | int32_t* /*outFences*/) { | ||
409 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
410 | if (adapter.getDisplayId() != display) { | ||
411 | return HWC2_ERROR_BAD_DISPLAY; | ||
412 | } | ||
413 | |||
414 | *outNumElements = 0; | ||
415 | return HWC2_ERROR_NONE; | ||
416 | } | ||
417 | |||
418 | int32_t createLayerHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t* outLayer) { | ||
419 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
420 | if (adapter.getDisplayId() != display) { | ||
421 | return HWC2_ERROR_BAD_DISPLAY; | ||
422 | } | ||
423 | |||
424 | *outLayer = adapter.addLayer(); | ||
425 | adapter.setState(HWC2OnFbAdapter::State::MODIFIED); | ||
426 | return HWC2_ERROR_NONE; | ||
427 | } | ||
428 | |||
429 | int32_t destroyLayerHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer) { | ||
430 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
431 | if (adapter.getDisplayId() != display) { | ||
432 | return HWC2_ERROR_BAD_DISPLAY; | ||
433 | } | ||
434 | |||
435 | if (adapter.removeLayer(layer)) { | ||
436 | adapter.setState(HWC2OnFbAdapter::State::MODIFIED); | ||
437 | return HWC2_ERROR_NONE; | ||
438 | } else { | ||
439 | return HWC2_ERROR_BAD_LAYER; | ||
440 | } | ||
441 | } | ||
442 | |||
443 | int32_t setCursorPositionHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t /*layer*/, | ||
444 | int32_t /*x*/, int32_t /*y*/) { | ||
445 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
446 | if (adapter.getDisplayId() != display) { | ||
447 | return HWC2_ERROR_BAD_DISPLAY; | ||
448 | } | ||
449 | |||
450 | // always an error | ||
451 | return HWC2_ERROR_BAD_LAYER; | ||
452 | } | ||
453 | |||
454 | int32_t setLayerBufferHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer, | ||
455 | buffer_handle_t /*buffer*/, int32_t acquireFence) { | ||
456 | if (acquireFence >= 0) { | ||
457 | sync_wait(acquireFence, -1); | ||
458 | close(acquireFence); | ||
459 | } | ||
460 | |||
461 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
462 | if (adapter.getDisplayId() != display) { | ||
463 | return HWC2_ERROR_BAD_DISPLAY; | ||
464 | } | ||
465 | if (!adapter.hasLayer(layer)) { | ||
466 | return HWC2_ERROR_BAD_LAYER; | ||
467 | } | ||
468 | |||
469 | // no state change | ||
470 | return HWC2_ERROR_NONE; | ||
471 | } | ||
472 | |||
473 | int32_t setLayerSurfaceDamageHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer, | ||
474 | hwc_region_t /*damage*/) { | ||
475 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
476 | if (adapter.getDisplayId() != display) { | ||
477 | return HWC2_ERROR_BAD_DISPLAY; | ||
478 | } | ||
479 | if (!adapter.hasLayer(layer)) { | ||
480 | return HWC2_ERROR_BAD_LAYER; | ||
481 | } | ||
482 | |||
483 | // no state change | ||
484 | return HWC2_ERROR_NONE; | ||
485 | } | ||
486 | |||
487 | int32_t setLayerCompositionTypeHook(hwc2_device_t* device, hwc2_display_t display, | ||
488 | hwc2_layer_t layer, int32_t type) { | ||
489 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
490 | if (adapter.getDisplayId() != display) { | ||
491 | return HWC2_ERROR_BAD_DISPLAY; | ||
492 | } | ||
493 | if (!adapter.markLayerDirty(layer, type != HWC2_COMPOSITION_CLIENT)) { | ||
494 | return HWC2_ERROR_BAD_LAYER; | ||
495 | } | ||
496 | |||
497 | adapter.setState(HWC2OnFbAdapter::State::MODIFIED); | ||
498 | return HWC2_ERROR_NONE; | ||
499 | } | ||
500 | |||
501 | template <typename... Args> | ||
502 | int32_t setLayerStateHook(hwc2_device_t* device, hwc2_display_t display, hwc2_layer_t layer, | ||
503 | Args... /*args*/) { | ||
504 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
505 | if (adapter.getDisplayId() != display) { | ||
506 | return HWC2_ERROR_BAD_DISPLAY; | ||
507 | } | ||
508 | if (!adapter.hasLayer(layer)) { | ||
509 | return HWC2_ERROR_BAD_LAYER; | ||
510 | } | ||
511 | |||
512 | adapter.setState(HWC2OnFbAdapter::State::MODIFIED); | ||
513 | return HWC2_ERROR_NONE; | ||
514 | } | ||
515 | |||
516 | template <typename PFN, typename T> | ||
517 | static hwc2_function_pointer_t asFP(T function) { | ||
518 | static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer"); | ||
519 | return reinterpret_cast<hwc2_function_pointer_t>(function); | ||
520 | } | ||
521 | |||
522 | hwc2_function_pointer_t getFunctionHook(hwc2_device_t* /*device*/, int32_t descriptor) { | ||
523 | switch (descriptor) { | ||
524 | // global functions | ||
525 | case HWC2_FUNCTION_DUMP: | ||
526 | return asFP<HWC2_PFN_DUMP>(dumpHook); | ||
527 | case HWC2_FUNCTION_REGISTER_CALLBACK: | ||
528 | return asFP<HWC2_PFN_REGISTER_CALLBACK>(registerCallbackHook); | ||
529 | |||
530 | // virtual display functions | ||
531 | case HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT: | ||
532 | return asFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(getMaxVirtualDisplayCountHook); | ||
533 | case HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY: | ||
534 | return asFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(createVirtualDisplayHook); | ||
535 | case HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY: | ||
536 | return asFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(destroyVirtualDisplayHook); | ||
537 | case HWC2_FUNCTION_SET_OUTPUT_BUFFER: | ||
538 | return asFP<HWC2_PFN_SET_OUTPUT_BUFFER>(setOutputBufferHook); | ||
539 | |||
540 | // display functions | ||
541 | case HWC2_FUNCTION_GET_DISPLAY_NAME: | ||
542 | return asFP<HWC2_PFN_GET_DISPLAY_NAME>(getDisplayNameHook); | ||
543 | case HWC2_FUNCTION_GET_DISPLAY_TYPE: | ||
544 | return asFP<HWC2_PFN_GET_DISPLAY_TYPE>(getDisplayTypeHook); | ||
545 | case HWC2_FUNCTION_GET_DOZE_SUPPORT: | ||
546 | return asFP<HWC2_PFN_GET_DOZE_SUPPORT>(getDozeSupportHook); | ||
547 | case HWC2_FUNCTION_GET_HDR_CAPABILITIES: | ||
548 | return asFP<HWC2_PFN_GET_HDR_CAPABILITIES>(getHdrCapabilitiesHook); | ||
549 | case HWC2_FUNCTION_SET_POWER_MODE: | ||
550 | return asFP<HWC2_PFN_SET_POWER_MODE>(setPowerModeHook); | ||
551 | case HWC2_FUNCTION_SET_VSYNC_ENABLED: | ||
552 | return asFP<HWC2_PFN_SET_VSYNC_ENABLED>(setVsyncEnabledHook); | ||
553 | case HWC2_FUNCTION_GET_COLOR_MODES: | ||
554 | return asFP<HWC2_PFN_GET_COLOR_MODES>(getColorModesHook); | ||
555 | case HWC2_FUNCTION_SET_COLOR_MODE: | ||
556 | return asFP<HWC2_PFN_SET_COLOR_MODE>(setColorModeHook); | ||
557 | case HWC2_FUNCTION_SET_COLOR_TRANSFORM: | ||
558 | return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook); | ||
559 | case HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT: | ||
560 | return asFP<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(getClientTargetSupportHook); | ||
561 | case HWC2_FUNCTION_SET_CLIENT_TARGET: | ||
562 | return asFP<HWC2_PFN_SET_CLIENT_TARGET>(setClientTargetHook); | ||
563 | |||
564 | // config functions | ||
565 | case HWC2_FUNCTION_GET_DISPLAY_CONFIGS: | ||
566 | return asFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(getDisplayConfigsHook); | ||
567 | case HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE: | ||
568 | return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(getDisplayAttributeHook); | ||
569 | case HWC2_FUNCTION_GET_ACTIVE_CONFIG: | ||
570 | return asFP<HWC2_PFN_GET_ACTIVE_CONFIG>(getActiveConfigHook); | ||
571 | case HWC2_FUNCTION_SET_ACTIVE_CONFIG: | ||
572 | return asFP<HWC2_PFN_SET_ACTIVE_CONFIG>(setActiveConfigHook); | ||
573 | |||
574 | // validate/present functions | ||
575 | case HWC2_FUNCTION_VALIDATE_DISPLAY: | ||
576 | return asFP<HWC2_PFN_VALIDATE_DISPLAY>(validateDisplayHook); | ||
577 | case HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES: | ||
578 | return asFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(getChangedCompositionTypesHook); | ||
579 | case HWC2_FUNCTION_GET_DISPLAY_REQUESTS: | ||
580 | return asFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(getDisplayRequestsHook); | ||
581 | case HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES: | ||
582 | return asFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(acceptDisplayChangesHook); | ||
583 | case HWC2_FUNCTION_PRESENT_DISPLAY: | ||
584 | return asFP<HWC2_PFN_PRESENT_DISPLAY>(presentDisplayHook); | ||
585 | case HWC2_FUNCTION_GET_RELEASE_FENCES: | ||
586 | return asFP<HWC2_PFN_GET_RELEASE_FENCES>(getReleaseFencesHook); | ||
587 | |||
588 | // layer create/destroy | ||
589 | case HWC2_FUNCTION_CREATE_LAYER: | ||
590 | return asFP<HWC2_PFN_CREATE_LAYER>(createLayerHook); | ||
591 | case HWC2_FUNCTION_DESTROY_LAYER: | ||
592 | return asFP<HWC2_PFN_DESTROY_LAYER>(destroyLayerHook); | ||
593 | |||
594 | // layer functions; validateDisplay not required | ||
595 | case HWC2_FUNCTION_SET_CURSOR_POSITION: | ||
596 | return asFP<HWC2_PFN_SET_CURSOR_POSITION>(setCursorPositionHook); | ||
597 | case HWC2_FUNCTION_SET_LAYER_BUFFER: | ||
598 | return asFP<HWC2_PFN_SET_LAYER_BUFFER>(setLayerBufferHook); | ||
599 | case HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE: | ||
600 | return asFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(setLayerSurfaceDamageHook); | ||
601 | |||
602 | // layer state functions; validateDisplay required | ||
603 | case HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE: | ||
604 | return asFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(setLayerCompositionTypeHook); | ||
605 | case HWC2_FUNCTION_SET_LAYER_BLEND_MODE: | ||
606 | return asFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(setLayerStateHook<int32_t>); | ||
607 | case HWC2_FUNCTION_SET_LAYER_COLOR: | ||
608 | return asFP<HWC2_PFN_SET_LAYER_COLOR>(setLayerStateHook<hwc_color_t>); | ||
609 | case HWC2_FUNCTION_SET_LAYER_DATASPACE: | ||
610 | return asFP<HWC2_PFN_SET_LAYER_DATASPACE>(setLayerStateHook<int32_t>); | ||
611 | case HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME: | ||
612 | return asFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(setLayerStateHook<hwc_rect_t>); | ||
613 | case HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA: | ||
614 | return asFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(setLayerStateHook<float>); | ||
615 | case HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM: | ||
616 | return asFP<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(setLayerStateHook<buffer_handle_t>); | ||
617 | case HWC2_FUNCTION_SET_LAYER_SOURCE_CROP: | ||
618 | return asFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(setLayerStateHook<hwc_frect_t>); | ||
619 | case HWC2_FUNCTION_SET_LAYER_TRANSFORM: | ||
620 | return asFP<HWC2_PFN_SET_LAYER_TRANSFORM>(setLayerStateHook<int32_t>); | ||
621 | case HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION: | ||
622 | return asFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(setLayerStateHook<hwc_region_t>); | ||
623 | case HWC2_FUNCTION_SET_LAYER_Z_ORDER: | ||
624 | return asFP<HWC2_PFN_SET_LAYER_Z_ORDER>(setLayerStateHook<uint32_t>); | ||
625 | |||
626 | default: | ||
627 | ALOGE("unknown function descriptor %d", descriptor); | ||
628 | return nullptr; | ||
629 | } | ||
630 | } | ||
631 | |||
632 | void getCapabilitiesHook(hwc2_device_t* /*device*/, uint32_t* outCount, | ||
633 | int32_t* /*outCapabilities*/) { | ||
634 | *outCount = 0; | ||
635 | } | ||
636 | |||
637 | int closeHook(hw_device_t* device) { | ||
638 | auto& adapter = HWC2OnFbAdapter::cast(device); | ||
639 | adapter.close(); | ||
640 | return 0; | ||
641 | } | ||
642 | |||
643 | } // anonymous namespace | ||
644 | |||
645 | HWC2OnFbAdapter::HWC2OnFbAdapter(framebuffer_device_t* fbDevice) | ||
646 | : hwc2_device_t(), mFbDevice(fbDevice) { | ||
647 | common.close = closeHook; | ||
648 | hwc2_device::getCapabilities = getCapabilitiesHook; | ||
649 | hwc2_device::getFunction = getFunctionHook; | ||
650 | |||
651 | mFbInfo.name = "fbdev"; | ||
652 | mFbInfo.width = mFbDevice->width; | ||
653 | mFbInfo.height = mFbDevice->height; | ||
654 | mFbInfo.format = mFbDevice->format; | ||
655 | mFbInfo.vsync_period_ns = int(1e9 / mFbDevice->fps); | ||
656 | mFbInfo.xdpi_scaled = int(mFbDevice->xdpi * 1000.0f); | ||
657 | mFbInfo.ydpi_scaled = int(mFbDevice->ydpi * 1000.0f); | ||
658 | |||
659 | mVsyncThread.start(0, mFbInfo.vsync_period_ns); | ||
660 | } | ||
661 | |||
662 | HWC2OnFbAdapter& HWC2OnFbAdapter::cast(hw_device_t* device) { | ||
663 | return *reinterpret_cast<HWC2OnFbAdapter*>(device); | ||
664 | } | ||
665 | |||
666 | HWC2OnFbAdapter& HWC2OnFbAdapter::cast(hwc2_device_t* device) { | ||
667 | return *reinterpret_cast<HWC2OnFbAdapter*>(device); | ||
668 | } | ||
669 | |||
670 | hwc2_display_t HWC2OnFbAdapter::getDisplayId() { | ||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | hwc2_config_t HWC2OnFbAdapter::getConfigId() { | ||
675 | return 0; | ||
676 | } | ||
677 | |||
678 | void HWC2OnFbAdapter::close() { | ||
679 | mVsyncThread.stop(); | ||
680 | framebuffer_close(mFbDevice); | ||
681 | } | ||
682 | |||
683 | const HWC2OnFbAdapter::Info& HWC2OnFbAdapter::getInfo() const { | ||
684 | return mFbInfo; | ||
685 | } | ||
686 | |||
687 | void HWC2OnFbAdapter::updateDebugString() { | ||
688 | if (mFbDevice->common.version >= 1 && mFbDevice->dump) { | ||
689 | char buffer[4096]; | ||
690 | mFbDevice->dump(mFbDevice, buffer, sizeof(buffer)); | ||
691 | buffer[sizeof(buffer) - 1] = '\0'; | ||
692 | |||
693 | mDebugString = buffer; | ||
694 | } | ||
695 | } | ||
696 | |||
697 | const std::string& HWC2OnFbAdapter::getDebugString() const { | ||
698 | return mDebugString; | ||
699 | } | ||
700 | |||
701 | void HWC2OnFbAdapter::setState(State state) { | ||
702 | mState = state; | ||
703 | } | ||
704 | |||
705 | HWC2OnFbAdapter::State HWC2OnFbAdapter::getState() const { | ||
706 | return mState; | ||
707 | } | ||
708 | |||
709 | hwc2_layer_t HWC2OnFbAdapter::addLayer() { | ||
710 | hwc2_layer_t id = ++mNextLayerId; | ||
711 | |||
712 | mLayers.insert(id); | ||
713 | mDirtyLayers.insert(id); | ||
714 | |||
715 | return id; | ||
716 | } | ||
717 | |||
718 | bool HWC2OnFbAdapter::removeLayer(hwc2_layer_t layer) { | ||
719 | mDirtyLayers.erase(layer); | ||
720 | return mLayers.erase(layer); | ||
721 | } | ||
722 | |||
723 | bool HWC2OnFbAdapter::hasLayer(hwc2_layer_t layer) const { | ||
724 | return mLayers.count(layer) > 0; | ||
725 | } | ||
726 | |||
727 | bool HWC2OnFbAdapter::markLayerDirty(hwc2_layer_t layer, bool dirty) { | ||
728 | if (mLayers.count(layer) == 0) { | ||
729 | return false; | ||
730 | } | ||
731 | |||
732 | if (dirty) { | ||
733 | mDirtyLayers.insert(layer); | ||
734 | } else { | ||
735 | mDirtyLayers.erase(layer); | ||
736 | } | ||
737 | |||
738 | return true; | ||
739 | } | ||
740 | |||
741 | const std::unordered_set<hwc2_layer_t>& HWC2OnFbAdapter::getDirtyLayers() const { | ||
742 | return mDirtyLayers; | ||
743 | } | ||
744 | |||
745 | void HWC2OnFbAdapter::clearDirtyLayers() { | ||
746 | mDirtyLayers.clear(); | ||
747 | } | ||
748 | |||
749 | /* | ||
750 | * For each frame, SurfaceFlinger | ||
751 | * | ||
752 | * - peforms GLES composition | ||
753 | * - calls eglSwapBuffers | ||
754 | * - calls setClientTarget, which maps to setBuffer below | ||
755 | * - calls presentDisplay, which maps to postBuffer below | ||
756 | * | ||
757 | * setBuffer should be a good place to call compositionComplete. | ||
758 | * | ||
759 | * As for post, it | ||
760 | * | ||
761 | * - schedules the buffer for presentation on the next vsync | ||
762 | * - locks the buffer and blocks all other users trying to lock it | ||
763 | * | ||
764 | * It does not give us a way to return a present fence, and we need to live | ||
765 | * with that. The implication is that, when we are double-buffered, | ||
766 | * SurfaceFlinger assumes the front buffer is available for rendering again | ||
767 | * immediately after the back buffer is posted. The locking semantics | ||
768 | * hopefully are strong enough that the rendering will be blocked. | ||
769 | */ | ||
770 | void HWC2OnFbAdapter::setBuffer(buffer_handle_t buffer) { | ||
771 | if (mFbDevice->compositionComplete) { | ||
772 | mFbDevice->compositionComplete(mFbDevice); | ||
773 | } | ||
774 | mBuffer = buffer; | ||
775 | } | ||
776 | |||
777 | bool HWC2OnFbAdapter::postBuffer() { | ||
778 | int error = 0; | ||
779 | if (mBuffer) { | ||
780 | error = mFbDevice->post(mFbDevice, mBuffer); | ||
781 | } | ||
782 | |||
783 | return error == 0; | ||
784 | } | ||
785 | |||
786 | void HWC2OnFbAdapter::setVsyncCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data) { | ||
787 | mVsyncThread.setCallback(callback, data); | ||
788 | } | ||
789 | |||
790 | void HWC2OnFbAdapter::enableVsync(bool enable) { | ||
791 | mVsyncThread.enableCallback(enable); | ||
792 | } | ||
793 | |||
794 | int64_t HWC2OnFbAdapter::VsyncThread::now() { | ||
795 | struct timespec ts; | ||
796 | clock_gettime(CLOCK_MONOTONIC, &ts); | ||
797 | |||
798 | return int64_t(ts.tv_sec) * 1'000'000'000 + ts.tv_nsec; | ||
799 | } | ||
800 | |||
801 | bool HWC2OnFbAdapter::VsyncThread::sleepUntil(int64_t t) { | ||
802 | struct timespec ts; | ||
803 | ts.tv_sec = t / 1'000'000'000; | ||
804 | ts.tv_nsec = t % 1'000'000'000; | ||
805 | |||
806 | while (true) { | ||
807 | int error = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ts, nullptr); | ||
808 | if (error) { | ||
809 | if (error == EINTR) { | ||
810 | continue; | ||
811 | } | ||
812 | return false; | ||
813 | } else { | ||
814 | return true; | ||
815 | } | ||
816 | } | ||
817 | } | ||
818 | |||
819 | void HWC2OnFbAdapter::VsyncThread::start(int64_t firstVsync, int64_t period) { | ||
820 | mNextVsync = firstVsync; | ||
821 | mPeriod = period; | ||
822 | mStarted = true; | ||
823 | mThread = std::thread(&VsyncThread::vsyncLoop, this); | ||
824 | } | ||
825 | |||
826 | void HWC2OnFbAdapter::VsyncThread::stop() { | ||
827 | { | ||
828 | std::lock_guard<std::mutex> lock(mMutex); | ||
829 | mStarted = false; | ||
830 | } | ||
831 | mCondition.notify_all(); | ||
832 | mThread.join(); | ||
833 | } | ||
834 | |||
835 | void HWC2OnFbAdapter::VsyncThread::setCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data) { | ||
836 | std::lock_guard<std::mutex> lock(mMutex); | ||
837 | mCallback = callback; | ||
838 | mCallbackData = data; | ||
839 | } | ||
840 | |||
841 | void HWC2OnFbAdapter::VsyncThread::enableCallback(bool enable) { | ||
842 | { | ||
843 | std::lock_guard<std::mutex> lock(mMutex); | ||
844 | mCallbackEnabled = enable; | ||
845 | } | ||
846 | mCondition.notify_all(); | ||
847 | } | ||
848 | |||
849 | void HWC2OnFbAdapter::VsyncThread::vsyncLoop() { | ||
850 | prctl(PR_SET_NAME, "VsyncThread", 0, 0, 0); | ||
851 | |||
852 | std::unique_lock<std::mutex> lock(mMutex); | ||
853 | if (!mStarted) { | ||
854 | return; | ||
855 | } | ||
856 | |||
857 | while (true) { | ||
858 | if (!mCallbackEnabled) { | ||
859 | mCondition.wait(lock, [this] { return mCallbackEnabled || !mStarted; }); | ||
860 | if (!mStarted) { | ||
861 | break; | ||
862 | } | ||
863 | } | ||
864 | |||
865 | lock.unlock(); | ||
866 | |||
867 | // adjust mNextVsync if necessary | ||
868 | int64_t t = now(); | ||
869 | if (mNextVsync < t) { | ||
870 | int64_t n = (t - mNextVsync + mPeriod - 1) / mPeriod; | ||
871 | mNextVsync += mPeriod * n; | ||
872 | } | ||
873 | bool fire = sleepUntil(mNextVsync); | ||
874 | |||
875 | lock.lock(); | ||
876 | |||
877 | if (fire) { | ||
878 | ALOGV("VsyncThread(%" PRId64 ")", mNextVsync); | ||
879 | if (mCallback) { | ||
880 | mCallback(mCallbackData, getDisplayId(), mNextVsync); | ||
881 | } | ||
882 | mNextVsync += mPeriod; | ||
883 | } | ||
884 | } | ||
885 | } | ||
886 | |||
887 | } // namespace android | ||
diff --git a/graphics/composer/2.1/utils/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h b/graphics/composer/2.1/utils/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h new file mode 100644 index 00000000..d6272fdb --- /dev/null +++ b/graphics/composer/2.1/utils/hwc2onfbadapter/include/hwc2onfbadapter/HWC2OnFbAdapter.h | |||
@@ -0,0 +1,123 @@ | |||
1 | /* | ||
2 | * Copyright 2017 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef ANDROID_SF_HWC2_ON_FB_ADAPTER_H | ||
18 | #define ANDROID_SF_HWC2_ON_FB_ADAPTER_H | ||
19 | |||
20 | #include <condition_variable> | ||
21 | #include <mutex> | ||
22 | #include <string> | ||
23 | #include <thread> | ||
24 | #include <unordered_set> | ||
25 | |||
26 | #include <hardware/hwcomposer2.h> | ||
27 | |||
28 | struct framebuffer_device_t; | ||
29 | |||
30 | namespace android { | ||
31 | |||
32 | class HWC2OnFbAdapter : public hwc2_device_t { | ||
33 | public: | ||
34 | HWC2OnFbAdapter(framebuffer_device_t* fbDevice); | ||
35 | |||
36 | static HWC2OnFbAdapter& cast(hw_device_t* device); | ||
37 | static HWC2OnFbAdapter& cast(hwc2_device_t* device); | ||
38 | |||
39 | static hwc2_display_t getDisplayId(); | ||
40 | static hwc2_config_t getConfigId(); | ||
41 | |||
42 | void close(); | ||
43 | |||
44 | struct Info { | ||
45 | std::string name; | ||
46 | uint32_t width; | ||
47 | uint32_t height; | ||
48 | int format; | ||
49 | int vsync_period_ns; | ||
50 | int xdpi_scaled; | ||
51 | int ydpi_scaled; | ||
52 | }; | ||
53 | const Info& getInfo() const; | ||
54 | |||
55 | void updateDebugString(); | ||
56 | const std::string& getDebugString() const; | ||
57 | |||
58 | enum class State { | ||
59 | MODIFIED, | ||
60 | VALIDATED_WITH_CHANGES, | ||
61 | VALIDATED, | ||
62 | }; | ||
63 | void setState(State state); | ||
64 | State getState() const; | ||
65 | |||
66 | hwc2_layer_t addLayer(); | ||
67 | bool removeLayer(hwc2_layer_t layer); | ||
68 | bool hasLayer(hwc2_layer_t layer) const; | ||
69 | bool markLayerDirty(hwc2_layer_t layer, bool dirty); | ||
70 | const std::unordered_set<hwc2_layer_t>& getDirtyLayers() const; | ||
71 | void clearDirtyLayers(); | ||
72 | |||
73 | void setBuffer(buffer_handle_t buffer); | ||
74 | bool postBuffer(); | ||
75 | |||
76 | void setVsyncCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data); | ||
77 | void enableVsync(bool enable); | ||
78 | |||
79 | private: | ||
80 | framebuffer_device_t* mFbDevice{nullptr}; | ||
81 | Info mFbInfo{}; | ||
82 | |||
83 | std::string mDebugString; | ||
84 | |||
85 | State mState{State::MODIFIED}; | ||
86 | |||
87 | uint64_t mNextLayerId{0}; | ||
88 | std::unordered_set<hwc2_layer_t> mLayers; | ||
89 | std::unordered_set<hwc2_layer_t> mDirtyLayers; | ||
90 | |||
91 | buffer_handle_t mBuffer{nullptr}; | ||
92 | |||
93 | class VsyncThread { | ||
94 | public: | ||
95 | static int64_t now(); | ||
96 | static bool sleepUntil(int64_t t); | ||
97 | |||
98 | void start(int64_t first, int64_t period); | ||
99 | void stop(); | ||
100 | void setCallback(HWC2_PFN_VSYNC callback, hwc2_callback_data_t data); | ||
101 | void enableCallback(bool enable); | ||
102 | |||
103 | private: | ||
104 | void vsyncLoop(); | ||
105 | bool waitUntilNextVsync(); | ||
106 | |||
107 | std::thread mThread; | ||
108 | int64_t mNextVsync{0}; | ||
109 | int64_t mPeriod{0}; | ||
110 | |||
111 | std::mutex mMutex; | ||
112 | std::condition_variable mCondition; | ||
113 | bool mStarted{false}; | ||
114 | HWC2_PFN_VSYNC mCallback{nullptr}; | ||
115 | hwc2_callback_data_t mCallbackData{nullptr}; | ||
116 | bool mCallbackEnabled{false}; | ||
117 | }; | ||
118 | VsyncThread mVsyncThread; | ||
119 | }; | ||
120 | |||
121 | } // namespace android | ||
122 | |||
123 | #endif // ANDROID_SF_HWC2_ON_FB_ADAPTER_H | ||
diff --git a/graphics/composer/2.1/utils/passthrough/Android.bp b/graphics/composer/2.1/utils/passthrough/Android.bp new file mode 100644 index 00000000..4d3c976a --- /dev/null +++ b/graphics/composer/2.1/utils/passthrough/Android.bp | |||
@@ -0,0 +1,22 @@ | |||
1 | cc_library_headers { | ||
2 | name: "android.hardware.graphics.composer@2.1-passthrough", | ||
3 | defaults: ["hidl_defaults"], | ||
4 | vendor: true, | ||
5 | shared_libs: [ | ||
6 | "libhardware", | ||
7 | "libhwc2on1adapter", | ||
8 | "libhwc2onfbadapter", | ||
9 | ], | ||
10 | export_shared_lib_headers: [ | ||
11 | "libhardware", | ||
12 | "libhwc2on1adapter", | ||
13 | "libhwc2onfbadapter", | ||
14 | ], | ||
15 | header_libs: [ | ||
16 | "android.hardware.graphics.composer@2.1-hal", | ||
17 | ], | ||
18 | export_header_lib_headers: [ | ||
19 | "android.hardware.graphics.composer@2.1-hal", | ||
20 | ], | ||
21 | export_include_dirs: ["include"], | ||
22 | } | ||
diff --git a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h new file mode 100644 index 00000000..964e75bd --- /dev/null +++ b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h | |||
@@ -0,0 +1,670 @@ | |||
1 | /* | ||
2 | * Copyright 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #pragma once | ||
18 | |||
19 | #ifndef LOG_TAG | ||
20 | #warning "HwcHal.h included without LOG_TAG" | ||
21 | #endif | ||
22 | |||
23 | #include <atomic> | ||
24 | #include <cstring> // for strerror | ||
25 | #include <type_traits> | ||
26 | #include <unordered_set> | ||
27 | #include <vector> | ||
28 | |||
29 | #include <android/hardware/graphics/composer/2.1/IComposer.h> | ||
30 | #include <composer-hal/2.1/ComposerHal.h> | ||
31 | #define HWC2_INCLUDE_STRINGIFICATION | ||
32 | #define HWC2_USE_CPP11 | ||
33 | #include <hardware/hwcomposer2.h> | ||
34 | #undef HWC2_INCLUDE_STRINGIFICATION | ||
35 | #undef HWC2_USE_CPP11 | ||
36 | #include <log/log.h> | ||
37 | |||
38 | namespace android { | ||
39 | namespace hardware { | ||
40 | namespace graphics { | ||
41 | namespace composer { | ||
42 | namespace V2_1 { | ||
43 | namespace passthrough { | ||
44 | |||
45 | namespace detail { | ||
46 | |||
47 | using android::hardware::graphics::common::V1_0::ColorMode; | ||
48 | using android::hardware::graphics::common::V1_0::ColorTransform; | ||
49 | using android::hardware::graphics::common::V1_0::Dataspace; | ||
50 | using android::hardware::graphics::common::V1_0::Hdr; | ||
51 | using android::hardware::graphics::common::V1_0::PixelFormat; | ||
52 | using android::hardware::graphics::common::V1_0::Transform; | ||
53 | |||
54 | // HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2 | ||
55 | template <typename Hal> | ||
56 | class HwcHalImpl : public Hal { | ||
57 | public: | ||
58 | virtual ~HwcHalImpl() { | ||
59 | if (mDevice) { | ||
60 | hwc2_close(mDevice); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | bool initWithModule(const hw_module_t* module) { | ||
65 | hwc2_device_t* device; | ||
66 | int result = hwc2_open(module, &device); | ||
67 | if (result) { | ||
68 | ALOGE("failed to open hwcomposer2 device: %s", strerror(-result)); | ||
69 | return false; | ||
70 | } | ||
71 | |||
72 | return initWithDevice(std::move(device), true); | ||
73 | } | ||
74 | |||
75 | bool initWithDevice(hwc2_device_t* device, bool requireReliablePresentFence) { | ||
76 | // we own the device from this point on | ||
77 | mDevice = device; | ||
78 | |||
79 | initCapabilities(); | ||
80 | if (requireReliablePresentFence && | ||
81 | hasCapability(HWC2_CAPABILITY_PRESENT_FENCE_IS_NOT_RELIABLE)) { | ||
82 | ALOGE("present fence must be reliable"); | ||
83 | mDevice->common.close(&mDevice->common); | ||
84 | mDevice = nullptr; | ||
85 | return false; | ||
86 | } | ||
87 | |||
88 | if (!initDispatch()) { | ||
89 | mDevice->common.close(&mDevice->common); | ||
90 | mDevice = nullptr; | ||
91 | return false; | ||
92 | } | ||
93 | |||
94 | return true; | ||
95 | } | ||
96 | |||
97 | bool hasCapability(hwc2_capability_t capability) override { | ||
98 | return (mCapabilities.count(capability) > 0); | ||
99 | } | ||
100 | |||
101 | std::string dumpDebugInfo() override { | ||
102 | uint32_t len = 0; | ||
103 | mDispatch.dump(mDevice, &len, nullptr); | ||
104 | |||
105 | std::vector<char> buf(len + 1); | ||
106 | mDispatch.dump(mDevice, &len, buf.data()); | ||
107 | buf.resize(len + 1); | ||
108 | buf[len] = '\0'; | ||
109 | |||
110 | return buf.data(); | ||
111 | } | ||
112 | |||
113 | void registerEventCallback(hal::ComposerHal::EventCallback* callback) override { | ||
114 | mMustValidateDisplay = true; | ||
115 | mEventCallback = callback; | ||
116 | |||
117 | mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, | ||
118 | reinterpret_cast<hwc2_function_pointer_t>(hotplugHook)); | ||
119 | mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this, | ||
120 | reinterpret_cast<hwc2_function_pointer_t>(refreshHook)); | ||
121 | mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this, | ||
122 | reinterpret_cast<hwc2_function_pointer_t>(vsyncHook)); | ||
123 | } | ||
124 | |||
125 | void unregisterEventCallback() override { | ||
126 | // we assume the callback functions | ||
127 | // | ||
128 | // - can be unregistered | ||
129 | // - can be in-flight | ||
130 | // - will never be called afterward | ||
131 | // | ||
132 | // which is likely incorrect | ||
133 | mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this, nullptr); | ||
134 | mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this, nullptr); | ||
135 | mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this, nullptr); | ||
136 | |||
137 | mEventCallback = nullptr; | ||
138 | } | ||
139 | |||
140 | uint32_t getMaxVirtualDisplayCount() override { | ||
141 | return mDispatch.getMaxVirtualDisplayCount(mDevice); | ||
142 | } | ||
143 | |||
144 | Error createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat* format, | ||
145 | Display* outDisplay) override { | ||
146 | int32_t hwc_format = static_cast<int32_t>(*format); | ||
147 | int32_t err = | ||
148 | mDispatch.createVirtualDisplay(mDevice, width, height, &hwc_format, outDisplay); | ||
149 | *format = static_cast<PixelFormat>(hwc_format); | ||
150 | |||
151 | return static_cast<Error>(err); | ||
152 | } | ||
153 | |||
154 | Error destroyVirtualDisplay(Display display) override { | ||
155 | int32_t err = mDispatch.destroyVirtualDisplay(mDevice, display); | ||
156 | return static_cast<Error>(err); | ||
157 | } | ||
158 | |||
159 | Error createLayer(Display display, Layer* outLayer) override { | ||
160 | int32_t err = mDispatch.createLayer(mDevice, display, outLayer); | ||
161 | return static_cast<Error>(err); | ||
162 | } | ||
163 | |||
164 | Error destroyLayer(Display display, Layer layer) override { | ||
165 | int32_t err = mDispatch.destroyLayer(mDevice, display, layer); | ||
166 | return static_cast<Error>(err); | ||
167 | } | ||
168 | |||
169 | Error getActiveConfig(Display display, Config* outConfig) override { | ||
170 | int32_t err = mDispatch.getActiveConfig(mDevice, display, outConfig); | ||
171 | return static_cast<Error>(err); | ||
172 | } | ||
173 | |||
174 | Error getClientTargetSupport(Display display, uint32_t width, uint32_t height, | ||
175 | PixelFormat format, Dataspace dataspace) override { | ||
176 | int32_t err = mDispatch.getClientTargetSupport(mDevice, display, width, height, | ||
177 | static_cast<int32_t>(format), | ||
178 | static_cast<int32_t>(dataspace)); | ||
179 | return static_cast<Error>(err); | ||
180 | } | ||
181 | |||
182 | Error getColorModes(Display display, hidl_vec<ColorMode>* outModes) override { | ||
183 | uint32_t count = 0; | ||
184 | int32_t err = mDispatch.getColorModes(mDevice, display, &count, nullptr); | ||
185 | if (err != HWC2_ERROR_NONE) { | ||
186 | return static_cast<Error>(err); | ||
187 | } | ||
188 | |||
189 | outModes->resize(count); | ||
190 | err = mDispatch.getColorModes( | ||
191 | mDevice, display, &count, | ||
192 | reinterpret_cast<std::underlying_type<ColorMode>::type*>(outModes->data())); | ||
193 | if (err != HWC2_ERROR_NONE) { | ||
194 | *outModes = hidl_vec<ColorMode>(); | ||
195 | return static_cast<Error>(err); | ||
196 | } | ||
197 | |||
198 | return Error::NONE; | ||
199 | } | ||
200 | |||
201 | Error getDisplayAttribute(Display display, Config config, IComposerClient::Attribute attribute, | ||
202 | int32_t* outValue) override { | ||
203 | int32_t err = mDispatch.getDisplayAttribute(mDevice, display, config, | ||
204 | static_cast<int32_t>(attribute), outValue); | ||
205 | return static_cast<Error>(err); | ||
206 | } | ||
207 | |||
208 | Error getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs) override { | ||
209 | uint32_t count = 0; | ||
210 | int32_t err = mDispatch.getDisplayConfigs(mDevice, display, &count, nullptr); | ||
211 | if (err != HWC2_ERROR_NONE) { | ||
212 | return static_cast<Error>(err); | ||
213 | } | ||
214 | |||
215 | outConfigs->resize(count); | ||
216 | err = mDispatch.getDisplayConfigs(mDevice, display, &count, outConfigs->data()); | ||
217 | if (err != HWC2_ERROR_NONE) { | ||
218 | *outConfigs = hidl_vec<Config>(); | ||
219 | return static_cast<Error>(err); | ||
220 | } | ||
221 | |||
222 | return Error::NONE; | ||
223 | } | ||
224 | |||
225 | Error getDisplayName(Display display, hidl_string* outName) override { | ||
226 | uint32_t count = 0; | ||
227 | int32_t err = mDispatch.getDisplayName(mDevice, display, &count, nullptr); | ||
228 | if (err != HWC2_ERROR_NONE) { | ||
229 | return static_cast<Error>(err); | ||
230 | } | ||
231 | |||
232 | std::vector<char> buf(count + 1); | ||
233 | err = mDispatch.getDisplayName(mDevice, display, &count, buf.data()); | ||
234 | if (err != HWC2_ERROR_NONE) { | ||
235 | return static_cast<Error>(err); | ||
236 | } | ||
237 | buf.resize(count + 1); | ||
238 | buf[count] = '\0'; | ||
239 | |||
240 | *outName = buf.data(); | ||
241 | |||
242 | return Error::NONE; | ||
243 | } | ||
244 | |||
245 | Error getDisplayType(Display display, IComposerClient::DisplayType* outType) override { | ||
246 | int32_t hwc_type = HWC2_DISPLAY_TYPE_INVALID; | ||
247 | int32_t err = mDispatch.getDisplayType(mDevice, display, &hwc_type); | ||
248 | *outType = static_cast<IComposerClient::DisplayType>(hwc_type); | ||
249 | |||
250 | return static_cast<Error>(err); | ||
251 | } | ||
252 | |||
253 | Error getDozeSupport(Display display, bool* outSupport) override { | ||
254 | int32_t hwc_support = 0; | ||
255 | int32_t err = mDispatch.getDozeSupport(mDevice, display, &hwc_support); | ||
256 | *outSupport = hwc_support; | ||
257 | |||
258 | return static_cast<Error>(err); | ||
259 | } | ||
260 | |||
261 | Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes, float* outMaxLuminance, | ||
262 | float* outMaxAverageLuminance, float* outMinLuminance) override { | ||
263 | uint32_t count = 0; | ||
264 | int32_t err = | ||
265 | mDispatch.getHdrCapabilities(mDevice, display, &count, nullptr, outMaxLuminance, | ||
266 | outMaxAverageLuminance, outMinLuminance); | ||
267 | if (err != HWC2_ERROR_NONE) { | ||
268 | return static_cast<Error>(err); | ||
269 | } | ||
270 | |||
271 | outTypes->resize(count); | ||
272 | err = mDispatch.getHdrCapabilities( | ||
273 | mDevice, display, &count, | ||
274 | reinterpret_cast<std::underlying_type<Hdr>::type*>(outTypes->data()), outMaxLuminance, | ||
275 | outMaxAverageLuminance, outMinLuminance); | ||
276 | if (err != HWC2_ERROR_NONE) { | ||
277 | *outTypes = hidl_vec<Hdr>(); | ||
278 | return static_cast<Error>(err); | ||
279 | } | ||
280 | |||
281 | return Error::NONE; | ||
282 | } | ||
283 | |||
284 | Error setActiveConfig(Display display, Config config) override { | ||
285 | int32_t err = mDispatch.setActiveConfig(mDevice, display, config); | ||
286 | return static_cast<Error>(err); | ||
287 | } | ||
288 | |||
289 | Error setColorMode(Display display, ColorMode mode) override { | ||
290 | int32_t err = mDispatch.setColorMode(mDevice, display, static_cast<int32_t>(mode)); | ||
291 | return static_cast<Error>(err); | ||
292 | } | ||
293 | |||
294 | Error setPowerMode(Display display, IComposerClient::PowerMode mode) override { | ||
295 | int32_t err = mDispatch.setPowerMode(mDevice, display, static_cast<int32_t>(mode)); | ||
296 | return static_cast<Error>(err); | ||
297 | } | ||
298 | |||
299 | Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled) override { | ||
300 | int32_t err = mDispatch.setVsyncEnabled(mDevice, display, static_cast<int32_t>(enabled)); | ||
301 | return static_cast<Error>(err); | ||
302 | } | ||
303 | |||
304 | Error setColorTransform(Display display, const float* matrix, int32_t hint) override { | ||
305 | int32_t err = mDispatch.setColorTransform(mDevice, display, matrix, hint); | ||
306 | return static_cast<Error>(err); | ||
307 | } | ||
308 | |||
309 | Error setClientTarget(Display display, buffer_handle_t target, int32_t acquireFence, | ||
310 | int32_t dataspace, const std::vector<hwc_rect_t>& damage) override { | ||
311 | hwc_region region = {damage.size(), damage.data()}; | ||
312 | int32_t err = | ||
313 | mDispatch.setClientTarget(mDevice, display, target, acquireFence, dataspace, region); | ||
314 | return static_cast<Error>(err); | ||
315 | } | ||
316 | |||
317 | Error setOutputBuffer(Display display, buffer_handle_t buffer, int32_t releaseFence) override { | ||
318 | int32_t err = mDispatch.setOutputBuffer(mDevice, display, buffer, releaseFence); | ||
319 | // unlike in setClientTarget, releaseFence is owned by us | ||
320 | if (err == HWC2_ERROR_NONE && releaseFence >= 0) { | ||
321 | close(releaseFence); | ||
322 | } | ||
323 | |||
324 | return static_cast<Error>(err); | ||
325 | } | ||
326 | |||
327 | Error validateDisplay(Display display, std::vector<Layer>* outChangedLayers, | ||
328 | std::vector<IComposerClient::Composition>* outCompositionTypes, | ||
329 | uint32_t* outDisplayRequestMask, std::vector<Layer>* outRequestedLayers, | ||
330 | std::vector<uint32_t>* outRequestMasks) override { | ||
331 | uint32_t typesCount = 0; | ||
332 | uint32_t reqsCount = 0; | ||
333 | int32_t err = mDispatch.validateDisplay(mDevice, display, &typesCount, &reqsCount); | ||
334 | mMustValidateDisplay = false; | ||
335 | |||
336 | if (err != HWC2_ERROR_NONE && err != HWC2_ERROR_HAS_CHANGES) { | ||
337 | return static_cast<Error>(err); | ||
338 | } | ||
339 | |||
340 | err = mDispatch.getChangedCompositionTypes(mDevice, display, &typesCount, nullptr, nullptr); | ||
341 | if (err != HWC2_ERROR_NONE) { | ||
342 | return static_cast<Error>(err); | ||
343 | } | ||
344 | |||
345 | std::vector<Layer> changedLayers(typesCount); | ||
346 | std::vector<IComposerClient::Composition> compositionTypes(typesCount); | ||
347 | err = mDispatch.getChangedCompositionTypes( | ||
348 | mDevice, display, &typesCount, changedLayers.data(), | ||
349 | reinterpret_cast<std::underlying_type<IComposerClient::Composition>::type*>( | ||
350 | compositionTypes.data())); | ||
351 | if (err != HWC2_ERROR_NONE) { | ||
352 | return static_cast<Error>(err); | ||
353 | } | ||
354 | |||
355 | int32_t displayReqs = 0; | ||
356 | err = mDispatch.getDisplayRequests(mDevice, display, &displayReqs, &reqsCount, nullptr, | ||
357 | nullptr); | ||
358 | if (err != HWC2_ERROR_NONE) { | ||
359 | return static_cast<Error>(err); | ||
360 | } | ||
361 | |||
362 | std::vector<Layer> requestedLayers(reqsCount); | ||
363 | std::vector<uint32_t> requestMasks(reqsCount); | ||
364 | err = mDispatch.getDisplayRequests(mDevice, display, &displayReqs, &reqsCount, | ||
365 | requestedLayers.data(), | ||
366 | reinterpret_cast<int32_t*>(requestMasks.data())); | ||
367 | if (err != HWC2_ERROR_NONE) { | ||
368 | return static_cast<Error>(err); | ||
369 | } | ||
370 | |||
371 | *outChangedLayers = std::move(changedLayers); | ||
372 | *outCompositionTypes = std::move(compositionTypes); | ||
373 | *outDisplayRequestMask = displayReqs; | ||
374 | *outRequestedLayers = std::move(requestedLayers); | ||
375 | *outRequestMasks = std::move(requestMasks); | ||
376 | |||
377 | return static_cast<Error>(err); | ||
378 | } | ||
379 | |||
380 | Error acceptDisplayChanges(Display display) override { | ||
381 | int32_t err = mDispatch.acceptDisplayChanges(mDevice, display); | ||
382 | return static_cast<Error>(err); | ||
383 | } | ||
384 | |||
385 | Error presentDisplay(Display display, int32_t* outPresentFence, std::vector<Layer>* outLayers, | ||
386 | std::vector<int32_t>* outReleaseFences) override { | ||
387 | if (mMustValidateDisplay) { | ||
388 | return Error::NOT_VALIDATED; | ||
389 | } | ||
390 | |||
391 | *outPresentFence = -1; | ||
392 | int32_t err = mDispatch.presentDisplay(mDevice, display, outPresentFence); | ||
393 | if (err != HWC2_ERROR_NONE) { | ||
394 | return static_cast<Error>(err); | ||
395 | } | ||
396 | |||
397 | uint32_t count = 0; | ||
398 | err = mDispatch.getReleaseFences(mDevice, display, &count, nullptr, nullptr); | ||
399 | if (err != HWC2_ERROR_NONE) { | ||
400 | ALOGW("failed to get release fences"); | ||
401 | return Error::NONE; | ||
402 | } | ||
403 | |||
404 | outLayers->resize(count); | ||
405 | outReleaseFences->resize(count); | ||
406 | err = mDispatch.getReleaseFences(mDevice, display, &count, outLayers->data(), | ||
407 | outReleaseFences->data()); | ||
408 | if (err != HWC2_ERROR_NONE) { | ||
409 | ALOGW("failed to get release fences"); | ||
410 | outLayers->clear(); | ||
411 | outReleaseFences->clear(); | ||
412 | return Error::NONE; | ||
413 | } | ||
414 | |||
415 | return static_cast<Error>(err); | ||
416 | } | ||
417 | |||
418 | Error setLayerCursorPosition(Display display, Layer layer, int32_t x, int32_t y) override { | ||
419 | int32_t err = mDispatch.setCursorPosition(mDevice, display, layer, x, y); | ||
420 | return static_cast<Error>(err); | ||
421 | } | ||
422 | |||
423 | Error setLayerBuffer(Display display, Layer layer, buffer_handle_t buffer, | ||
424 | int32_t acquireFence) override { | ||
425 | int32_t err = mDispatch.setLayerBuffer(mDevice, display, layer, buffer, acquireFence); | ||
426 | return static_cast<Error>(err); | ||
427 | } | ||
428 | |||
429 | Error setLayerSurfaceDamage(Display display, Layer layer, | ||
430 | const std::vector<hwc_rect_t>& damage) override { | ||
431 | hwc_region region = {damage.size(), damage.data()}; | ||
432 | int32_t err = mDispatch.setLayerSurfaceDamage(mDevice, display, layer, region); | ||
433 | return static_cast<Error>(err); | ||
434 | } | ||
435 | |||
436 | Error setLayerBlendMode(Display display, Layer layer, int32_t mode) override { | ||
437 | int32_t err = mDispatch.setLayerBlendMode(mDevice, display, layer, mode); | ||
438 | return static_cast<Error>(err); | ||
439 | } | ||
440 | |||
441 | Error setLayerColor(Display display, Layer layer, IComposerClient::Color color) override { | ||
442 | hwc_color_t hwc_color{color.r, color.g, color.b, color.a}; | ||
443 | int32_t err = mDispatch.setLayerColor(mDevice, display, layer, hwc_color); | ||
444 | return static_cast<Error>(err); | ||
445 | } | ||
446 | |||
447 | Error setLayerCompositionType(Display display, Layer layer, int32_t type) override { | ||
448 | int32_t err = mDispatch.setLayerCompositionType(mDevice, display, layer, type); | ||
449 | return static_cast<Error>(err); | ||
450 | } | ||
451 | |||
452 | Error setLayerDataspace(Display display, Layer layer, int32_t dataspace) override { | ||
453 | int32_t err = mDispatch.setLayerDataspace(mDevice, display, layer, dataspace); | ||
454 | return static_cast<Error>(err); | ||
455 | } | ||
456 | |||
457 | Error setLayerDisplayFrame(Display display, Layer layer, const hwc_rect_t& frame) override { | ||
458 | int32_t err = mDispatch.setLayerDisplayFrame(mDevice, display, layer, frame); | ||
459 | return static_cast<Error>(err); | ||
460 | } | ||
461 | |||
462 | Error setLayerPlaneAlpha(Display display, Layer layer, float alpha) override { | ||
463 | int32_t err = mDispatch.setLayerPlaneAlpha(mDevice, display, layer, alpha); | ||
464 | return static_cast<Error>(err); | ||
465 | } | ||
466 | |||
467 | Error setLayerSidebandStream(Display display, Layer layer, buffer_handle_t stream) override { | ||
468 | int32_t err = mDispatch.setLayerSidebandStream(mDevice, display, layer, stream); | ||
469 | return static_cast<Error>(err); | ||
470 | } | ||
471 | |||
472 | Error setLayerSourceCrop(Display display, Layer layer, const hwc_frect_t& crop) override { | ||
473 | int32_t err = mDispatch.setLayerSourceCrop(mDevice, display, layer, crop); | ||
474 | return static_cast<Error>(err); | ||
475 | } | ||
476 | |||
477 | Error setLayerTransform(Display display, Layer layer, int32_t transform) override { | ||
478 | int32_t err = mDispatch.setLayerTransform(mDevice, display, layer, transform); | ||
479 | return static_cast<Error>(err); | ||
480 | } | ||
481 | |||
482 | Error setLayerVisibleRegion(Display display, Layer layer, | ||
483 | const std::vector<hwc_rect_t>& visible) override { | ||
484 | hwc_region_t region = {visible.size(), visible.data()}; | ||
485 | int32_t err = mDispatch.setLayerVisibleRegion(mDevice, display, layer, region); | ||
486 | return static_cast<Error>(err); | ||
487 | } | ||
488 | |||
489 | Error setLayerZOrder(Display display, Layer layer, uint32_t z) override { | ||
490 | int32_t err = mDispatch.setLayerZOrder(mDevice, display, layer, z); | ||
491 | return static_cast<Error>(err); | ||
492 | } | ||
493 | |||
494 | protected: | ||
495 | virtual void initCapabilities() { | ||
496 | uint32_t count = 0; | ||
497 | mDevice->getCapabilities(mDevice, &count, nullptr); | ||
498 | |||
499 | std::vector<int32_t> caps(count); | ||
500 | mDevice->getCapabilities(mDevice, &count, caps.data()); | ||
501 | caps.resize(count); | ||
502 | |||
503 | mCapabilities.reserve(count); | ||
504 | for (auto cap : caps) { | ||
505 | mCapabilities.insert(static_cast<hwc2_capability_t>(cap)); | ||
506 | } | ||
507 | } | ||
508 | |||
509 | template <typename T> | ||
510 | bool initDispatch(hwc2_function_descriptor_t desc, T* outPfn) { | ||
511 | auto pfn = mDevice->getFunction(mDevice, desc); | ||
512 | if (pfn) { | ||
513 | *outPfn = reinterpret_cast<T>(pfn); | ||
514 | return true; | ||
515 | } else { | ||
516 | ALOGE("failed to get hwcomposer2 function %d", desc); | ||
517 | return false; | ||
518 | } | ||
519 | } | ||
520 | |||
521 | virtual bool initDispatch() { | ||
522 | if (!initDispatch(HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES, &mDispatch.acceptDisplayChanges) || | ||
523 | !initDispatch(HWC2_FUNCTION_CREATE_LAYER, &mDispatch.createLayer) || | ||
524 | !initDispatch(HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY, &mDispatch.createVirtualDisplay) || | ||
525 | !initDispatch(HWC2_FUNCTION_DESTROY_LAYER, &mDispatch.destroyLayer) || | ||
526 | !initDispatch(HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY, | ||
527 | &mDispatch.destroyVirtualDisplay) || | ||
528 | !initDispatch(HWC2_FUNCTION_DUMP, &mDispatch.dump) || | ||
529 | !initDispatch(HWC2_FUNCTION_GET_ACTIVE_CONFIG, &mDispatch.getActiveConfig) || | ||
530 | !initDispatch(HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES, | ||
531 | &mDispatch.getChangedCompositionTypes) || | ||
532 | !initDispatch(HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT, | ||
533 | &mDispatch.getClientTargetSupport) || | ||
534 | !initDispatch(HWC2_FUNCTION_GET_COLOR_MODES, &mDispatch.getColorModes) || | ||
535 | !initDispatch(HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE, &mDispatch.getDisplayAttribute) || | ||
536 | !initDispatch(HWC2_FUNCTION_GET_DISPLAY_CONFIGS, &mDispatch.getDisplayConfigs) || | ||
537 | !initDispatch(HWC2_FUNCTION_GET_DISPLAY_NAME, &mDispatch.getDisplayName) || | ||
538 | !initDispatch(HWC2_FUNCTION_GET_DISPLAY_REQUESTS, &mDispatch.getDisplayRequests) || | ||
539 | !initDispatch(HWC2_FUNCTION_GET_DISPLAY_TYPE, &mDispatch.getDisplayType) || | ||
540 | !initDispatch(HWC2_FUNCTION_GET_DOZE_SUPPORT, &mDispatch.getDozeSupport) || | ||
541 | !initDispatch(HWC2_FUNCTION_GET_HDR_CAPABILITIES, &mDispatch.getHdrCapabilities) || | ||
542 | !initDispatch(HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT, | ||
543 | &mDispatch.getMaxVirtualDisplayCount) || | ||
544 | !initDispatch(HWC2_FUNCTION_GET_RELEASE_FENCES, &mDispatch.getReleaseFences) || | ||
545 | !initDispatch(HWC2_FUNCTION_PRESENT_DISPLAY, &mDispatch.presentDisplay) || | ||
546 | !initDispatch(HWC2_FUNCTION_REGISTER_CALLBACK, &mDispatch.registerCallback) || | ||
547 | !initDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG, &mDispatch.setActiveConfig) || | ||
548 | !initDispatch(HWC2_FUNCTION_SET_CLIENT_TARGET, &mDispatch.setClientTarget) || | ||
549 | !initDispatch(HWC2_FUNCTION_SET_COLOR_MODE, &mDispatch.setColorMode) || | ||
550 | !initDispatch(HWC2_FUNCTION_SET_COLOR_TRANSFORM, &mDispatch.setColorTransform) || | ||
551 | !initDispatch(HWC2_FUNCTION_SET_CURSOR_POSITION, &mDispatch.setCursorPosition) || | ||
552 | !initDispatch(HWC2_FUNCTION_SET_LAYER_BLEND_MODE, &mDispatch.setLayerBlendMode) || | ||
553 | !initDispatch(HWC2_FUNCTION_SET_LAYER_BUFFER, &mDispatch.setLayerBuffer) || | ||
554 | !initDispatch(HWC2_FUNCTION_SET_LAYER_COLOR, &mDispatch.setLayerColor) || | ||
555 | !initDispatch(HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE, | ||
556 | &mDispatch.setLayerCompositionType) || | ||
557 | !initDispatch(HWC2_FUNCTION_SET_LAYER_DATASPACE, &mDispatch.setLayerDataspace) || | ||
558 | !initDispatch(HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME, &mDispatch.setLayerDisplayFrame) || | ||
559 | !initDispatch(HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA, &mDispatch.setLayerPlaneAlpha)) { | ||
560 | return false; | ||
561 | } | ||
562 | |||
563 | if (hasCapability(HWC2_CAPABILITY_SIDEBAND_STREAM)) { | ||
564 | if (!initDispatch(HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM, | ||
565 | &mDispatch.setLayerSidebandStream)) { | ||
566 | return false; | ||
567 | } | ||
568 | } | ||
569 | |||
570 | if (!initDispatch(HWC2_FUNCTION_SET_LAYER_SOURCE_CROP, &mDispatch.setLayerSourceCrop) || | ||
571 | !initDispatch(HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE, | ||
572 | &mDispatch.setLayerSurfaceDamage) || | ||
573 | !initDispatch(HWC2_FUNCTION_SET_LAYER_TRANSFORM, &mDispatch.setLayerTransform) || | ||
574 | !initDispatch(HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION, | ||
575 | &mDispatch.setLayerVisibleRegion) || | ||
576 | !initDispatch(HWC2_FUNCTION_SET_LAYER_Z_ORDER, &mDispatch.setLayerZOrder) || | ||
577 | !initDispatch(HWC2_FUNCTION_SET_OUTPUT_BUFFER, &mDispatch.setOutputBuffer) || | ||
578 | !initDispatch(HWC2_FUNCTION_SET_POWER_MODE, &mDispatch.setPowerMode) || | ||
579 | !initDispatch(HWC2_FUNCTION_SET_VSYNC_ENABLED, &mDispatch.setVsyncEnabled) || | ||
580 | !initDispatch(HWC2_FUNCTION_VALIDATE_DISPLAY, &mDispatch.validateDisplay)) { | ||
581 | return false; | ||
582 | } | ||
583 | |||
584 | return true; | ||
585 | } | ||
586 | |||
587 | static void hotplugHook(hwc2_callback_data_t callbackData, hwc2_display_t display, | ||
588 | int32_t connected) { | ||
589 | auto hal = static_cast<HwcHalImpl*>(callbackData); | ||
590 | hal->mEventCallback->onHotplug(display, | ||
591 | static_cast<IComposerCallback::Connection>(connected)); | ||
592 | } | ||
593 | |||
594 | static void refreshHook(hwc2_callback_data_t callbackData, hwc2_display_t display) { | ||
595 | auto hal = static_cast<HwcHalImpl*>(callbackData); | ||
596 | hal->mMustValidateDisplay = true; | ||
597 | hal->mEventCallback->onRefresh(display); | ||
598 | } | ||
599 | |||
600 | static void vsyncHook(hwc2_callback_data_t callbackData, hwc2_display_t display, | ||
601 | int64_t timestamp) { | ||
602 | auto hal = static_cast<HwcHalImpl*>(callbackData); | ||
603 | hal->mEventCallback->onVsync(display, timestamp); | ||
604 | } | ||
605 | |||
606 | hwc2_device_t* mDevice = nullptr; | ||
607 | |||
608 | std::unordered_set<hwc2_capability_t> mCapabilities; | ||
609 | |||
610 | struct { | ||
611 | HWC2_PFN_ACCEPT_DISPLAY_CHANGES acceptDisplayChanges; | ||
612 | HWC2_PFN_CREATE_LAYER createLayer; | ||
613 | HWC2_PFN_CREATE_VIRTUAL_DISPLAY createVirtualDisplay; | ||
614 | HWC2_PFN_DESTROY_LAYER destroyLayer; | ||
615 | HWC2_PFN_DESTROY_VIRTUAL_DISPLAY destroyVirtualDisplay; | ||
616 | HWC2_PFN_DUMP dump; | ||
617 | HWC2_PFN_GET_ACTIVE_CONFIG getActiveConfig; | ||
618 | HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES getChangedCompositionTypes; | ||
619 | HWC2_PFN_GET_CLIENT_TARGET_SUPPORT getClientTargetSupport; | ||
620 | HWC2_PFN_GET_COLOR_MODES getColorModes; | ||
621 | HWC2_PFN_GET_DISPLAY_ATTRIBUTE getDisplayAttribute; | ||
622 | HWC2_PFN_GET_DISPLAY_CONFIGS getDisplayConfigs; | ||
623 | HWC2_PFN_GET_DISPLAY_NAME getDisplayName; | ||
624 | HWC2_PFN_GET_DISPLAY_REQUESTS getDisplayRequests; | ||
625 | HWC2_PFN_GET_DISPLAY_TYPE getDisplayType; | ||
626 | HWC2_PFN_GET_DOZE_SUPPORT getDozeSupport; | ||
627 | HWC2_PFN_GET_HDR_CAPABILITIES getHdrCapabilities; | ||
628 | HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT getMaxVirtualDisplayCount; | ||
629 | HWC2_PFN_GET_RELEASE_FENCES getReleaseFences; | ||
630 | HWC2_PFN_PRESENT_DISPLAY presentDisplay; | ||
631 | HWC2_PFN_REGISTER_CALLBACK registerCallback; | ||
632 | HWC2_PFN_SET_ACTIVE_CONFIG setActiveConfig; | ||
633 | HWC2_PFN_SET_CLIENT_TARGET setClientTarget; | ||
634 | HWC2_PFN_SET_COLOR_MODE setColorMode; | ||
635 | HWC2_PFN_SET_COLOR_TRANSFORM setColorTransform; | ||
636 | HWC2_PFN_SET_CURSOR_POSITION setCursorPosition; | ||
637 | HWC2_PFN_SET_LAYER_BLEND_MODE setLayerBlendMode; | ||
638 | HWC2_PFN_SET_LAYER_BUFFER setLayerBuffer; | ||
639 | HWC2_PFN_SET_LAYER_COLOR setLayerColor; | ||
640 | HWC2_PFN_SET_LAYER_COMPOSITION_TYPE setLayerCompositionType; | ||
641 | HWC2_PFN_SET_LAYER_DATASPACE setLayerDataspace; | ||
642 | HWC2_PFN_SET_LAYER_DISPLAY_FRAME setLayerDisplayFrame; | ||
643 | HWC2_PFN_SET_LAYER_PLANE_ALPHA setLayerPlaneAlpha; | ||
644 | HWC2_PFN_SET_LAYER_SIDEBAND_STREAM setLayerSidebandStream; | ||
645 | HWC2_PFN_SET_LAYER_SOURCE_CROP setLayerSourceCrop; | ||
646 | HWC2_PFN_SET_LAYER_SURFACE_DAMAGE setLayerSurfaceDamage; | ||
647 | HWC2_PFN_SET_LAYER_TRANSFORM setLayerTransform; | ||
648 | HWC2_PFN_SET_LAYER_VISIBLE_REGION setLayerVisibleRegion; | ||
649 | HWC2_PFN_SET_LAYER_Z_ORDER setLayerZOrder; | ||
650 | HWC2_PFN_SET_OUTPUT_BUFFER setOutputBuffer; | ||
651 | HWC2_PFN_SET_POWER_MODE setPowerMode; | ||
652 | HWC2_PFN_SET_VSYNC_ENABLED setVsyncEnabled; | ||
653 | HWC2_PFN_VALIDATE_DISPLAY validateDisplay; | ||
654 | } mDispatch = {}; | ||
655 | |||
656 | hal::ComposerHal::EventCallback* mEventCallback = nullptr; | ||
657 | |||
658 | std::atomic<bool> mMustValidateDisplay{true}; | ||
659 | }; | ||
660 | |||
661 | } // namespace detail | ||
662 | |||
663 | using HwcHal = detail::HwcHalImpl<hal::ComposerHal>; | ||
664 | |||
665 | } // namespace passthrough | ||
666 | } // namespace V2_1 | ||
667 | } // namespace composer | ||
668 | } // namespace graphics | ||
669 | } // namespace hardware | ||
670 | } // namespace android | ||
diff --git a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h new file mode 100644 index 00000000..33c914dd --- /dev/null +++ b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h | |||
@@ -0,0 +1,152 @@ | |||
1 | /* | ||
2 | * Copyright 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #pragma once | ||
18 | |||
19 | #ifndef LOG_TAG | ||
20 | #warning "HwcLoader.h included without LOG_TAG" | ||
21 | #endif | ||
22 | |||
23 | #include <memory> | ||
24 | |||
25 | #include <composer-hal/2.1/Composer.h> | ||
26 | #include <composer-passthrough/2.1/HwcHal.h> | ||
27 | #include <hardware/fb.h> | ||
28 | #include <hardware/gralloc.h> | ||
29 | #include <hardware/hardware.h> | ||
30 | #include <hardware/hwcomposer.h> | ||
31 | #include <hardware/hwcomposer2.h> | ||
32 | #include <hwc2on1adapter/HWC2On1Adapter.h> | ||
33 | #include <hwc2onfbadapter/HWC2OnFbAdapter.h> | ||
34 | #include <log/log.h> | ||
35 | |||
36 | namespace android { | ||
37 | namespace hardware { | ||
38 | namespace graphics { | ||
39 | namespace composer { | ||
40 | namespace V2_1 { | ||
41 | namespace passthrough { | ||
42 | |||
43 | class HwcLoader { | ||
44 | public: | ||
45 | static IComposer* load() { | ||
46 | const hw_module_t* module = loadModule(); | ||
47 | if (!module) { | ||
48 | return nullptr; | ||
49 | } | ||
50 | |||
51 | auto hal = createHalWithAdapter(module); | ||
52 | if (!hal) { | ||
53 | return nullptr; | ||
54 | } | ||
55 | |||
56 | return createComposer(std::move(hal)); | ||
57 | } | ||
58 | |||
59 | // load hwcomposer2 module | ||
60 | static const hw_module_t* loadModule() { | ||
61 | const hw_module_t* module; | ||
62 | int error = hw_get_module(HWC_HARDWARE_MODULE_ID, &module); | ||
63 | if (error) { | ||
64 | ALOGI("falling back to gralloc module"); | ||
65 | error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); | ||
66 | } | ||
67 | |||
68 | if (error) { | ||
69 | ALOGE("failed to get hwcomposer or gralloc module"); | ||
70 | return nullptr; | ||
71 | } | ||
72 | |||
73 | return module; | ||
74 | } | ||
75 | |||
76 | // create a ComposerHal instance | ||
77 | static std::unique_ptr<hal::ComposerHal> createHal(const hw_module_t* module) { | ||
78 | auto hal = std::make_unique<HwcHal>(); | ||
79 | return hal->initWithModule(module) ? std::move(hal) : nullptr; | ||
80 | } | ||
81 | |||
82 | // create a ComposerHal instance, insert an adapter if necessary | ||
83 | static std::unique_ptr<hal::ComposerHal> createHalWithAdapter(const hw_module_t* module) { | ||
84 | bool adapted; | ||
85 | hwc2_device_t* device = openDeviceWithAdapter(module, &adapted); | ||
86 | if (!device) { | ||
87 | return nullptr; | ||
88 | } | ||
89 | auto hal = std::make_unique<HwcHal>(); | ||
90 | return hal->initWithDevice(std::move(device), !adapted) ? std::move(hal) : nullptr; | ||
91 | } | ||
92 | |||
93 | // create an IComposer instance | ||
94 | static IComposer* createComposer(std::unique_ptr<hal::ComposerHal> hal) { | ||
95 | return hal::Composer::create(std::move(hal)).release(); | ||
96 | } | ||
97 | |||
98 | protected: | ||
99 | // open hwcomposer2 device, install an adapter if necessary | ||
100 | static hwc2_device_t* openDeviceWithAdapter(const hw_module_t* module, bool* outAdapted) { | ||
101 | if (module->id && std::string(module->id) == GRALLOC_HARDWARE_MODULE_ID) { | ||
102 | *outAdapted = true; | ||
103 | return adaptGrallocModule(module); | ||
104 | } | ||
105 | |||
106 | hw_device_t* device; | ||
107 | int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device); | ||
108 | if (error) { | ||
109 | ALOGE("failed to open hwcomposer device: %s", strerror(-error)); | ||
110 | return nullptr; | ||
111 | } | ||
112 | |||
113 | int major = (device->version >> 24) & 0xf; | ||
114 | if (major != 2) { | ||
115 | *outAdapted = true; | ||
116 | return adaptHwc1Device(std::move(reinterpret_cast<hwc_composer_device_1*>(device))); | ||
117 | } | ||
118 | |||
119 | *outAdapted = false; | ||
120 | return reinterpret_cast<hwc2_device_t*>(device); | ||
121 | } | ||
122 | |||
123 | private: | ||
124 | static hwc2_device_t* adaptGrallocModule(const hw_module_t* module) { | ||
125 | framebuffer_device_t* device; | ||
126 | int error = framebuffer_open(module, &device); | ||
127 | if (error) { | ||
128 | ALOGE("failed to open framebuffer device: %s", strerror(-error)); | ||
129 | return nullptr; | ||
130 | } | ||
131 | |||
132 | return new HWC2OnFbAdapter(device); | ||
133 | } | ||
134 | |||
135 | static hwc2_device_t* adaptHwc1Device(hwc_composer_device_1* device) { | ||
136 | int minor = (device->common.version >> 16) & 0xf; | ||
137 | if (minor < 1) { | ||
138 | ALOGE("hwcomposer 1.0 is not supported"); | ||
139 | device->common.close(&device->common); | ||
140 | return nullptr; | ||
141 | } | ||
142 | |||
143 | return new HWC2On1Adapter(device); | ||
144 | } | ||
145 | }; | ||
146 | |||
147 | } // namespace passthrough | ||
148 | } // namespace V2_1 | ||
149 | } // namespace composer | ||
150 | } // namespace graphics | ||
151 | } // namespace hardware | ||
152 | } // namespace android | ||
diff --git a/graphics/composer/2.1/utils/vts/Android.bp b/graphics/composer/2.1/utils/vts/Android.bp new file mode 100644 index 00000000..846cfdf3 --- /dev/null +++ b/graphics/composer/2.1/utils/vts/Android.bp | |||
@@ -0,0 +1,38 @@ | |||
1 | // | ||
2 | // Copyright (C) 2016 The Android Open Source Project | ||
3 | // | ||
4 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | // you may not use this file except in compliance with the License. | ||
6 | // You may obtain a copy of the License at | ||
7 | // | ||
8 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | // | ||
10 | // Unless required by applicable law or agreed to in writing, software | ||
11 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | // See the License for the specific language governing permissions and | ||
14 | // limitations under the License. | ||
15 | // | ||
16 | |||
17 | cc_library_static { | ||
18 | name: "android.hardware.graphics.composer@2.1-vts", | ||
19 | defaults: ["hidl_defaults"], | ||
20 | srcs: [ | ||
21 | "ComposerVts.cpp", | ||
22 | "GraphicsComposerCallback.cpp", | ||
23 | "TestCommandReader.cpp", | ||
24 | ], | ||
25 | static_libs: [ | ||
26 | "VtsHalHidlTargetTestBase", | ||
27 | "android.hardware.graphics.composer@2.1", | ||
28 | ], | ||
29 | header_libs: [ | ||
30 | "android.hardware.graphics.composer@2.1-command-buffer", | ||
31 | ], | ||
32 | cflags: [ | ||
33 | "-O0", | ||
34 | "-g", | ||
35 | "-DLOG_TAG=\"ComposerVts\"", | ||
36 | ], | ||
37 | export_include_dirs: ["include"], | ||
38 | } | ||
diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp new file mode 100644 index 00000000..2f531b41 --- /dev/null +++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp | |||
@@ -0,0 +1,324 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include <composer-vts/2.1/ComposerVts.h> | ||
18 | |||
19 | #include <VtsHalHidlTargetTestBase.h> | ||
20 | |||
21 | namespace android { | ||
22 | namespace hardware { | ||
23 | namespace graphics { | ||
24 | namespace composer { | ||
25 | namespace V2_1 { | ||
26 | namespace vts { | ||
27 | |||
28 | Composer::Composer() { | ||
29 | mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>(); | ||
30 | init(); | ||
31 | } | ||
32 | |||
33 | Composer::Composer(const std::string& name) { | ||
34 | mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>(name); | ||
35 | init(); | ||
36 | } | ||
37 | |||
38 | void Composer::init() { | ||
39 | ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service"; | ||
40 | |||
41 | std::vector<IComposer::Capability> capabilities = getCapabilities(); | ||
42 | mCapabilities.insert(capabilities.begin(), capabilities.end()); | ||
43 | } | ||
44 | |||
45 | sp<IComposer> Composer::getRaw() const { | ||
46 | return mComposer; | ||
47 | } | ||
48 | |||
49 | bool Composer::hasCapability(IComposer::Capability capability) const { | ||
50 | return mCapabilities.count(capability) > 0; | ||
51 | } | ||
52 | |||
53 | std::vector<IComposer::Capability> Composer::getCapabilities() { | ||
54 | std::vector<IComposer::Capability> capabilities; | ||
55 | mComposer->getCapabilities( | ||
56 | [&](const auto& tmpCapabilities) { capabilities = tmpCapabilities; }); | ||
57 | |||
58 | return capabilities; | ||
59 | } | ||
60 | |||
61 | std::string Composer::dumpDebugInfo() { | ||
62 | std::string debugInfo; | ||
63 | mComposer->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); }); | ||
64 | |||
65 | return debugInfo; | ||
66 | } | ||
67 | |||
68 | std::unique_ptr<ComposerClient> Composer::createClient() { | ||
69 | std::unique_ptr<ComposerClient> client; | ||
70 | mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) { | ||
71 | ASSERT_EQ(Error::NONE, tmpError) << "failed to create client"; | ||
72 | client = std::make_unique<ComposerClient>(tmpClient); | ||
73 | }); | ||
74 | |||
75 | return client; | ||
76 | } | ||
77 | |||
78 | ComposerClient::ComposerClient(const sp<IComposerClient>& client) : mClient(client) {} | ||
79 | |||
80 | ComposerClient::~ComposerClient() { | ||
81 | for (auto it : mDisplayResources) { | ||
82 | Display display = it.first; | ||
83 | DisplayResource& resource = it.second; | ||
84 | |||
85 | for (auto layer : resource.layers) { | ||
86 | EXPECT_EQ(Error::NONE, mClient->destroyLayer(display, layer)) | ||
87 | << "failed to destroy layer " << layer; | ||
88 | } | ||
89 | |||
90 | if (resource.isVirtual) { | ||
91 | EXPECT_EQ(Error::NONE, mClient->destroyVirtualDisplay(display)) | ||
92 | << "failed to destroy virtual display " << display; | ||
93 | } | ||
94 | } | ||
95 | mDisplayResources.clear(); | ||
96 | } | ||
97 | |||
98 | sp<IComposerClient> ComposerClient::getRaw() const { | ||
99 | return mClient; | ||
100 | } | ||
101 | |||
102 | void ComposerClient::registerCallback(const sp<IComposerCallback>& callback) { | ||
103 | mClient->registerCallback(callback); | ||
104 | } | ||
105 | |||
106 | uint32_t ComposerClient::getMaxVirtualDisplayCount() { | ||
107 | return mClient->getMaxVirtualDisplayCount(); | ||
108 | } | ||
109 | |||
110 | Display ComposerClient::createVirtualDisplay(uint32_t width, uint32_t height, | ||
111 | PixelFormat formatHint, uint32_t outputBufferSlotCount, | ||
112 | PixelFormat* outFormat) { | ||
113 | Display display = 0; | ||
114 | mClient->createVirtualDisplay( | ||
115 | width, height, formatHint, outputBufferSlotCount, | ||
116 | [&](const auto& tmpError, const auto& tmpDisplay, const auto& tmpFormat) { | ||
117 | ASSERT_EQ(Error::NONE, tmpError) << "failed to create virtual display"; | ||
118 | display = tmpDisplay; | ||
119 | *outFormat = tmpFormat; | ||
120 | |||
121 | ASSERT_TRUE(mDisplayResources.insert({display, DisplayResource(true)}).second) | ||
122 | << "duplicated virtual display id " << display; | ||
123 | }); | ||
124 | |||
125 | return display; | ||
126 | } | ||
127 | |||
128 | void ComposerClient::destroyVirtualDisplay(Display display) { | ||
129 | Error error = mClient->destroyVirtualDisplay(display); | ||
130 | ASSERT_EQ(Error::NONE, error) << "failed to destroy virtual display " << display; | ||
131 | |||
132 | mDisplayResources.erase(display); | ||
133 | } | ||
134 | |||
135 | Layer ComposerClient::createLayer(Display display, uint32_t bufferSlotCount) { | ||
136 | Layer layer = 0; | ||
137 | mClient->createLayer(display, bufferSlotCount, [&](const auto& tmpError, const auto& tmpLayer) { | ||
138 | ASSERT_EQ(Error::NONE, tmpError) << "failed to create layer"; | ||
139 | layer = tmpLayer; | ||
140 | |||
141 | auto resourceIt = mDisplayResources.find(display); | ||
142 | if (resourceIt == mDisplayResources.end()) { | ||
143 | resourceIt = mDisplayResources.insert({display, DisplayResource(false)}).first; | ||
144 | } | ||
145 | |||
146 | ASSERT_TRUE(resourceIt->second.layers.insert(layer).second) | ||
147 | << "duplicated layer id " << layer; | ||
148 | }); | ||
149 | |||
150 | return layer; | ||
151 | } | ||
152 | |||
153 | void ComposerClient::destroyLayer(Display display, Layer layer) { | ||
154 | Error error = mClient->destroyLayer(display, layer); | ||
155 | ASSERT_EQ(Error::NONE, error) << "failed to destroy layer " << layer; | ||
156 | |||
157 | auto resourceIt = mDisplayResources.find(display); | ||
158 | ASSERT_NE(mDisplayResources.end(), resourceIt); | ||
159 | resourceIt->second.layers.erase(layer); | ||
160 | } | ||
161 | |||
162 | Config ComposerClient::getActiveConfig(Display display) { | ||
163 | Config config = 0; | ||
164 | mClient->getActiveConfig(display, [&](const auto& tmpError, const auto& tmpConfig) { | ||
165 | ASSERT_EQ(Error::NONE, tmpError) << "failed to get active config"; | ||
166 | config = tmpConfig; | ||
167 | }); | ||
168 | |||
169 | return config; | ||
170 | } | ||
171 | |||
172 | bool ComposerClient::getClientTargetSupport(Display display, uint32_t width, uint32_t height, | ||
173 | PixelFormat format, Dataspace dataspace) { | ||
174 | Error error = mClient->getClientTargetSupport(display, width, height, format, dataspace); | ||
175 | return error == Error::NONE; | ||
176 | } | ||
177 | |||
178 | std::vector<ColorMode> ComposerClient::getColorModes(Display display) { | ||
179 | std::vector<ColorMode> modes; | ||
180 | mClient->getColorModes(display, [&](const auto& tmpError, const auto& tmpMode) { | ||
181 | ASSERT_EQ(Error::NONE, tmpError) << "failed to get color mode"; | ||
182 | modes = tmpMode; | ||
183 | }); | ||
184 | |||
185 | return modes; | ||
186 | } | ||
187 | |||
188 | int32_t ComposerClient::getDisplayAttribute(Display display, Config config, | ||
189 | IComposerClient::Attribute attribute) { | ||
190 | int32_t value = 0; | ||
191 | mClient->getDisplayAttribute( | ||
192 | display, config, attribute, [&](const auto& tmpError, const auto& tmpValue) { | ||
193 | ASSERT_EQ(Error::NONE, tmpError) << "failed to get display attribute"; | ||
194 | value = tmpValue; | ||
195 | }); | ||
196 | |||
197 | return value; | ||
198 | } | ||
199 | |||
200 | std::vector<Config> ComposerClient::getDisplayConfigs(Display display) { | ||
201 | std::vector<Config> configs; | ||
202 | mClient->getDisplayConfigs(display, [&](const auto& tmpError, const auto& tmpConfigs) { | ||
203 | ASSERT_EQ(Error::NONE, tmpError) << "failed to get display configs"; | ||
204 | configs = tmpConfigs; | ||
205 | }); | ||
206 | |||
207 | return configs; | ||
208 | } | ||
209 | |||
210 | std::string ComposerClient::getDisplayName(Display display) { | ||
211 | std::string name; | ||
212 | mClient->getDisplayName(display, [&](const auto& tmpError, const auto& tmpName) { | ||
213 | ASSERT_EQ(Error::NONE, tmpError) << "failed to get display name"; | ||
214 | name = tmpName.c_str(); | ||
215 | }); | ||
216 | |||
217 | return name; | ||
218 | } | ||
219 | |||
220 | IComposerClient::DisplayType ComposerClient::getDisplayType(Display display) { | ||
221 | IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID; | ||
222 | mClient->getDisplayType(display, [&](const auto& tmpError, const auto& tmpType) { | ||
223 | ASSERT_EQ(Error::NONE, tmpError) << "failed to get display type"; | ||
224 | type = tmpType; | ||
225 | }); | ||
226 | |||
227 | return type; | ||
228 | } | ||
229 | |||
230 | bool ComposerClient::getDozeSupport(Display display) { | ||
231 | bool support = false; | ||
232 | mClient->getDozeSupport(display, [&](const auto& tmpError, const auto& tmpSupport) { | ||
233 | ASSERT_EQ(Error::NONE, tmpError) << "failed to get doze support"; | ||
234 | support = tmpSupport; | ||
235 | }); | ||
236 | |||
237 | return support; | ||
238 | } | ||
239 | |||
240 | std::vector<Hdr> ComposerClient::getHdrCapabilities(Display display, float* outMaxLuminance, | ||
241 | float* outMaxAverageLuminance, | ||
242 | float* outMinLuminance) { | ||
243 | std::vector<Hdr> types; | ||
244 | mClient->getHdrCapabilities( | ||
245 | display, [&](const auto& tmpError, const auto& tmpTypes, const auto& tmpMaxLuminance, | ||
246 | const auto& tmpMaxAverageLuminance, const auto& tmpMinLuminance) { | ||
247 | ASSERT_EQ(Error::NONE, tmpError) << "failed to get HDR capabilities"; | ||
248 | types = tmpTypes; | ||
249 | *outMaxLuminance = tmpMaxLuminance; | ||
250 | *outMaxAverageLuminance = tmpMaxAverageLuminance; | ||
251 | *outMinLuminance = tmpMinLuminance; | ||
252 | }); | ||
253 | |||
254 | return types; | ||
255 | } | ||
256 | |||
257 | void ComposerClient::setClientTargetSlotCount(Display display, uint32_t clientTargetSlotCount) { | ||
258 | Error error = mClient->setClientTargetSlotCount(display, clientTargetSlotCount); | ||
259 | ASSERT_EQ(Error::NONE, error) << "failed to set client target slot count"; | ||
260 | } | ||
261 | |||
262 | void ComposerClient::setActiveConfig(Display display, Config config) { | ||
263 | Error error = mClient->setActiveConfig(display, config); | ||
264 | ASSERT_EQ(Error::NONE, error) << "failed to set active config"; | ||
265 | } | ||
266 | |||
267 | void ComposerClient::setColorMode(Display display, ColorMode mode) { | ||
268 | Error error = mClient->setColorMode(display, mode); | ||
269 | ASSERT_EQ(Error::NONE, error) << "failed to set color mode"; | ||
270 | } | ||
271 | |||
272 | void ComposerClient::setPowerMode(Display display, IComposerClient::PowerMode mode) { | ||
273 | Error error = mClient->setPowerMode(display, mode); | ||
274 | ASSERT_EQ(Error::NONE, error) << "failed to set power mode"; | ||
275 | } | ||
276 | |||
277 | void ComposerClient::setVsyncEnabled(Display display, bool enabled) { | ||
278 | IComposerClient::Vsync vsync = | ||
279 | (enabled) ? IComposerClient::Vsync::ENABLE : IComposerClient::Vsync::DISABLE; | ||
280 | Error error = mClient->setVsyncEnabled(display, vsync); | ||
281 | ASSERT_EQ(Error::NONE, error) << "failed to set vsync mode"; | ||
282 | |||
283 | // give the hwbinder thread some time to handle any pending vsync callback | ||
284 | if (!enabled) { | ||
285 | usleep(5 * 1000); | ||
286 | } | ||
287 | } | ||
288 | |||
289 | void ComposerClient::execute(TestCommandReader* reader, CommandWriterBase* writer) { | ||
290 | bool queueChanged = false; | ||
291 | uint32_t commandLength = 0; | ||
292 | hidl_vec<hidl_handle> commandHandles; | ||
293 | ASSERT_TRUE(writer->writeQueue(&queueChanged, &commandLength, &commandHandles)); | ||
294 | |||
295 | if (queueChanged) { | ||
296 | auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor()); | ||
297 | ASSERT_EQ(Error::NONE, static_cast<Error>(ret)); | ||
298 | return; | ||
299 | } | ||
300 | |||
301 | mClient->executeCommands(commandLength, commandHandles, | ||
302 | [&](const auto& tmpError, const auto& tmpOutQueueChanged, | ||
303 | const auto& tmpOutLength, const auto& tmpOutHandles) { | ||
304 | ASSERT_EQ(Error::NONE, tmpError); | ||
305 | |||
306 | if (tmpOutQueueChanged) { | ||
307 | mClient->getOutputCommandQueue( | ||
308 | [&](const auto& tmpError, const auto& tmpDescriptor) { | ||
309 | ASSERT_EQ(Error::NONE, tmpError); | ||
310 | reader->setMQDescriptor(tmpDescriptor); | ||
311 | }); | ||
312 | } | ||
313 | |||
314 | ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles)); | ||
315 | reader->parse(); | ||
316 | }); | ||
317 | } | ||
318 | |||
319 | } // namespace vts | ||
320 | } // namespace V2_1 | ||
321 | } // namespace composer | ||
322 | } // namespace graphics | ||
323 | } // namespace hardware | ||
324 | } // namespace android | ||
diff --git a/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.cpp b/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp index 0ad440c1..1ead138e 100644 --- a/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.cpp +++ b/graphics/composer/2.1/utils/vts/GraphicsComposerCallback.cpp | |||
@@ -14,78 +14,77 @@ | |||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "GraphicsComposerCallback.h" | 17 | #include <composer-vts/2.1/GraphicsComposerCallback.h> |
18 | 18 | ||
19 | namespace android { | 19 | namespace android { |
20 | namespace hardware { | 20 | namespace hardware { |
21 | namespace graphics { | 21 | namespace graphics { |
22 | namespace composer { | 22 | namespace composer { |
23 | namespace V2_1 { | 23 | namespace V2_1 { |
24 | namespace tests { | 24 | namespace vts { |
25 | 25 | ||
26 | void GraphicsComposerCallback::setVsyncAllowed(bool allowed) { | 26 | void GraphicsComposerCallback::setVsyncAllowed(bool allowed) { |
27 | std::lock_guard<std::mutex> lock(mMutex); | 27 | std::lock_guard<std::mutex> lock(mMutex); |
28 | mVsyncAllowed = allowed; | 28 | mVsyncAllowed = allowed; |
29 | } | 29 | } |
30 | 30 | ||
31 | std::vector<Display> GraphicsComposerCallback::getDisplays() const { | 31 | std::vector<Display> GraphicsComposerCallback::getDisplays() const { |
32 | std::lock_guard<std::mutex> lock(mMutex); | 32 | std::lock_guard<std::mutex> lock(mMutex); |
33 | return std::vector<Display>(mDisplays.begin(), mDisplays.end()); | 33 | return std::vector<Display>(mDisplays.begin(), mDisplays.end()); |
34 | } | 34 | } |
35 | 35 | ||
36 | int GraphicsComposerCallback::getInvalidHotplugCount() const { | 36 | int GraphicsComposerCallback::getInvalidHotplugCount() const { |
37 | std::lock_guard<std::mutex> lock(mMutex); | 37 | std::lock_guard<std::mutex> lock(mMutex); |
38 | return mInvalidHotplugCount; | 38 | return mInvalidHotplugCount; |
39 | } | 39 | } |
40 | 40 | ||
41 | int GraphicsComposerCallback::getInvalidRefreshCount() const { | 41 | int GraphicsComposerCallback::getInvalidRefreshCount() const { |
42 | std::lock_guard<std::mutex> lock(mMutex); | 42 | std::lock_guard<std::mutex> lock(mMutex); |
43 | return mInvalidRefreshCount; | 43 | return mInvalidRefreshCount; |
44 | } | 44 | } |
45 | 45 | ||
46 | int GraphicsComposerCallback::getInvalidVsyncCount() const { | 46 | int GraphicsComposerCallback::getInvalidVsyncCount() const { |
47 | std::lock_guard<std::mutex> lock(mMutex); | 47 | std::lock_guard<std::mutex> lock(mMutex); |
48 | return mInvalidVsyncCount; | 48 | return mInvalidVsyncCount; |
49 | } | 49 | } |
50 | 50 | ||
51 | Return<void> GraphicsComposerCallback::onHotplug(Display display, | 51 | Return<void> GraphicsComposerCallback::onHotplug(Display display, Connection connection) { |
52 | Connection connection) { | 52 | std::lock_guard<std::mutex> lock(mMutex); |
53 | std::lock_guard<std::mutex> lock(mMutex); | 53 | |
54 | 54 | if (connection == Connection::CONNECTED) { | |
55 | if (connection == Connection::CONNECTED) { | 55 | if (!mDisplays.insert(display).second) { |
56 | if (!mDisplays.insert(display).second) { | 56 | mInvalidHotplugCount++; |
57 | mInvalidHotplugCount++; | 57 | } |
58 | } | 58 | } else if (connection == Connection::DISCONNECTED) { |
59 | } else if (connection == Connection::DISCONNECTED) { | 59 | if (!mDisplays.erase(display)) { |
60 | if (!mDisplays.erase(display)) { | 60 | mInvalidHotplugCount++; |
61 | mInvalidHotplugCount++; | 61 | } |
62 | } | 62 | } |
63 | } | ||
64 | 63 | ||
65 | return Void(); | 64 | return Void(); |
66 | } | 65 | } |
67 | 66 | ||
68 | Return<void> GraphicsComposerCallback::onRefresh(Display display) { | 67 | Return<void> GraphicsComposerCallback::onRefresh(Display display) { |
69 | std::lock_guard<std::mutex> lock(mMutex); | 68 | std::lock_guard<std::mutex> lock(mMutex); |
70 | 69 | ||
71 | if (mDisplays.count(display) == 0) { | 70 | if (mDisplays.count(display) == 0) { |
72 | mInvalidRefreshCount++; | 71 | mInvalidRefreshCount++; |
73 | } | 72 | } |
74 | 73 | ||
75 | return Void(); | 74 | return Void(); |
76 | } | 75 | } |
77 | 76 | ||
78 | Return<void> GraphicsComposerCallback::onVsync(Display display, int64_t) { | 77 | Return<void> GraphicsComposerCallback::onVsync(Display display, int64_t) { |
79 | std::lock_guard<std::mutex> lock(mMutex); | 78 | std::lock_guard<std::mutex> lock(mMutex); |
80 | 79 | ||
81 | if (!mVsyncAllowed || mDisplays.count(display) == 0) { | 80 | if (!mVsyncAllowed || mDisplays.count(display) == 0) { |
82 | mInvalidVsyncCount++; | 81 | mInvalidVsyncCount++; |
83 | } | 82 | } |
84 | 83 | ||
85 | return Void(); | 84 | return Void(); |
86 | } | 85 | } |
87 | 86 | ||
88 | } // namespace tests | 87 | } // namespace vts |
89 | } // namespace V2_1 | 88 | } // namespace V2_1 |
90 | } // namespace composer | 89 | } // namespace composer |
91 | } // namespace graphics | 90 | } // namespace graphics |
diff --git a/graphics/composer/2.1/utils/vts/TestCommandReader.cpp b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp new file mode 100644 index 00000000..6f8f1ad4 --- /dev/null +++ b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include <composer-vts/2.1/TestCommandReader.h> | ||
18 | |||
19 | #include <gtest/gtest.h> | ||
20 | |||
21 | namespace android { | ||
22 | namespace hardware { | ||
23 | namespace graphics { | ||
24 | namespace composer { | ||
25 | namespace V2_1 { | ||
26 | namespace vts { | ||
27 | |||
28 | void TestCommandReader::parse() { | ||
29 | while (!isEmpty()) { | ||
30 | IComposerClient::Command command; | ||
31 | uint16_t length; | ||
32 | ASSERT_TRUE(beginCommand(&command, &length)); | ||
33 | |||
34 | switch (command) { | ||
35 | case IComposerClient::Command::SET_ERROR: { | ||
36 | ASSERT_EQ(2, length); | ||
37 | auto loc = read(); | ||
38 | auto err = readSigned(); | ||
39 | GTEST_FAIL() << "unexpected error " << err << " at location " << loc; | ||
40 | } break; | ||
41 | case IComposerClient::Command::SELECT_DISPLAY: | ||
42 | case IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES: | ||
43 | case IComposerClient::Command::SET_DISPLAY_REQUESTS: | ||
44 | case IComposerClient::Command::SET_PRESENT_FENCE: | ||
45 | case IComposerClient::Command::SET_RELEASE_FENCES: | ||
46 | break; | ||
47 | default: | ||
48 | GTEST_FAIL() << "unexpected return command " << std::hex | ||
49 | << static_cast<int>(command); | ||
50 | break; | ||
51 | } | ||
52 | |||
53 | endCommand(); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | } // namespace vts | ||
58 | } // namespace V2_1 | ||
59 | } // namespace composer | ||
60 | } // namespace graphics | ||
61 | } // namespace hardware | ||
62 | } // namespace android | ||
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h new file mode 100644 index 00000000..0d883e4f --- /dev/null +++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/ComposerVts.h | |||
@@ -0,0 +1,126 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #pragma once | ||
18 | |||
19 | #include <memory> | ||
20 | #include <string> | ||
21 | #include <unordered_map> | ||
22 | #include <unordered_set> | ||
23 | #include <vector> | ||
24 | |||
25 | #include <android/hardware/graphics/composer/2.1/IComposer.h> | ||
26 | #include <composer-command-buffer/2.1/ComposerCommandBuffer.h> | ||
27 | #include <composer-vts/2.1/TestCommandReader.h> | ||
28 | #include <utils/StrongPointer.h> | ||
29 | |||
30 | namespace android { | ||
31 | namespace hardware { | ||
32 | namespace graphics { | ||
33 | namespace composer { | ||
34 | namespace V2_1 { | ||
35 | namespace vts { | ||
36 | |||
37 | using android::hardware::graphics::common::V1_0::ColorMode; | ||
38 | using android::hardware::graphics::common::V1_0::Dataspace; | ||
39 | using android::hardware::graphics::common::V1_0::Hdr; | ||
40 | using android::hardware::graphics::common::V1_0::PixelFormat; | ||
41 | |||
42 | class ComposerClient; | ||
43 | |||
44 | // A wrapper to IComposer. | ||
45 | class Composer { | ||
46 | public: | ||
47 | Composer(); | ||
48 | explicit Composer(const std::string& name); | ||
49 | |||
50 | sp<IComposer> getRaw() const; | ||
51 | |||
52 | // Returns true when the composer supports the specified capability. | ||
53 | bool hasCapability(IComposer::Capability capability) const; | ||
54 | |||
55 | std::vector<IComposer::Capability> getCapabilities(); | ||
56 | std::string dumpDebugInfo(); | ||
57 | std::unique_ptr<ComposerClient> createClient(); | ||
58 | |||
59 | protected: | ||
60 | sp<IComposer> mComposer; | ||
61 | |||
62 | private: | ||
63 | void init(); | ||
64 | |||
65 | std::unordered_set<IComposer::Capability> mCapabilities; | ||
66 | }; | ||
67 | |||
68 | // A wrapper to IComposerClient. | ||
69 | class ComposerClient { | ||
70 | public: | ||
71 | ComposerClient(const sp<IComposerClient>& client); | ||
72 | ~ComposerClient(); | ||
73 | |||
74 | sp<IComposerClient> getRaw() const; | ||
75 | |||
76 | void registerCallback(const sp<IComposerCallback>& callback); | ||
77 | uint32_t getMaxVirtualDisplayCount(); | ||
78 | |||
79 | Display createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat formatHint, | ||
80 | uint32_t outputBufferSlotCount, PixelFormat* outFormat); | ||
81 | void destroyVirtualDisplay(Display display); | ||
82 | |||
83 | Layer createLayer(Display display, uint32_t bufferSlotCount); | ||
84 | void destroyLayer(Display display, Layer layer); | ||
85 | |||
86 | Config getActiveConfig(Display display); | ||
87 | bool getClientTargetSupport(Display display, uint32_t width, uint32_t height, | ||
88 | PixelFormat format, Dataspace dataspace); | ||
89 | std::vector<ColorMode> getColorModes(Display display); | ||
90 | int32_t getDisplayAttribute(Display display, Config config, | ||
91 | IComposerClient::Attribute attribute); | ||
92 | std::vector<Config> getDisplayConfigs(Display display); | ||
93 | std::string getDisplayName(Display display); | ||
94 | IComposerClient::DisplayType getDisplayType(Display display); | ||
95 | bool getDozeSupport(Display display); | ||
96 | std::vector<Hdr> getHdrCapabilities(Display display, float* outMaxLuminance, | ||
97 | float* outMaxAverageLuminance, float* outMinLuminance); | ||
98 | |||
99 | void setClientTargetSlotCount(Display display, uint32_t clientTargetSlotCount); | ||
100 | void setActiveConfig(Display display, Config config); | ||
101 | void setColorMode(Display display, ColorMode mode); | ||
102 | void setPowerMode(Display display, IComposerClient::PowerMode mode); | ||
103 | void setVsyncEnabled(Display display, bool enabled); | ||
104 | |||
105 | void execute(TestCommandReader* reader, CommandWriterBase* writer); | ||
106 | |||
107 | private: | ||
108 | sp<IComposerClient> mClient; | ||
109 | |||
110 | // Keep track of all virtual displays and layers. When a test fails with | ||
111 | // ASSERT_*, the destructor will clean up the resources for the test. | ||
112 | struct DisplayResource { | ||
113 | DisplayResource(bool isVirtual_) : isVirtual(isVirtual_) {} | ||
114 | |||
115 | bool isVirtual; | ||
116 | std::unordered_set<Layer> layers; | ||
117 | }; | ||
118 | std::unordered_map<Display, DisplayResource> mDisplayResources; | ||
119 | }; | ||
120 | |||
121 | } // namespace vts | ||
122 | } // namespace V2_1 | ||
123 | } // namespace composer | ||
124 | } // namespace graphics | ||
125 | } // namespace hardware | ||
126 | } // namespace android | ||
diff --git a/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h index e3320865..e3c348f7 100644 --- a/graphics/composer/2.1/vts/functional/GraphicsComposerCallback.h +++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/GraphicsComposerCallback.h | |||
@@ -14,8 +14,7 @@ | |||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifndef GRAPHICS_COMPOSER_CALLBACK_H | 17 | #pragma once |
18 | #define GRAPHICS_COMPOSER_CALLBACK_H | ||
19 | 18 | ||
20 | #include <android/hardware/graphics/composer/2.1/IComposerCallback.h> | 19 | #include <android/hardware/graphics/composer/2.1/IComposerCallback.h> |
21 | 20 | ||
@@ -27,43 +26,41 @@ namespace hardware { | |||
27 | namespace graphics { | 26 | namespace graphics { |
28 | namespace composer { | 27 | namespace composer { |
29 | namespace V2_1 { | 28 | namespace V2_1 { |
30 | namespace tests { | 29 | namespace vts { |
31 | 30 | ||
32 | // IComposerCallback to be installed with IComposerClient::registerCallback. | 31 | // IComposerCallback to be installed with IComposerClient::registerCallback. |
33 | class GraphicsComposerCallback : public IComposerCallback { | 32 | class GraphicsComposerCallback : public IComposerCallback { |
34 | public: | 33 | public: |
35 | void setVsyncAllowed(bool allowed); | 34 | void setVsyncAllowed(bool allowed); |
36 | 35 | ||
37 | std::vector<Display> getDisplays() const; | 36 | std::vector<Display> getDisplays() const; |
38 | 37 | ||
39 | int getInvalidHotplugCount() const; | 38 | int getInvalidHotplugCount() const; |
40 | 39 | ||
41 | int getInvalidRefreshCount() const; | 40 | int getInvalidRefreshCount() const; |
42 | 41 | ||
43 | int getInvalidVsyncCount() const; | 42 | int getInvalidVsyncCount() const; |
44 | 43 | ||
45 | private: | 44 | private: |
46 | Return<void> onHotplug(Display display, Connection connection) override; | 45 | Return<void> onHotplug(Display display, Connection connection) override; |
47 | Return<void> onRefresh(Display display) override; | 46 | Return<void> onRefresh(Display display) override; |
48 | Return<void> onVsync(Display display, int64_t) override; | 47 | Return<void> onVsync(Display display, int64_t) override; |
49 | 48 | ||
50 | mutable std::mutex mMutex; | 49 | mutable std::mutex mMutex; |
51 | // the set of all currently connected displays | 50 | // the set of all currently connected displays |
52 | std::unordered_set<Display> mDisplays; | 51 | std::unordered_set<Display> mDisplays; |
53 | // true only when vsync is enabled | 52 | // true only when vsync is enabled |
54 | bool mVsyncAllowed = true; | 53 | bool mVsyncAllowed = true; |
55 | 54 | ||
56 | // track invalid callbacks | 55 | // track invalid callbacks |
57 | int mInvalidHotplugCount = 0; | 56 | int mInvalidHotplugCount = 0; |
58 | int mInvalidRefreshCount = 0; | 57 | int mInvalidRefreshCount = 0; |
59 | int mInvalidVsyncCount = 0; | 58 | int mInvalidVsyncCount = 0; |
60 | }; | 59 | }; |
61 | 60 | ||
62 | } // namespace tests | 61 | } // namespace vts |
63 | } // namespace V2_1 | 62 | } // namespace V2_1 |
64 | } // namespace composer | 63 | } // namespace composer |
65 | } // namespace graphics | 64 | } // namespace graphics |
66 | } // namespace hardware | 65 | } // namespace hardware |
67 | } // namespace android | 66 | } // namespace android |
68 | |||
69 | #endif // GRAPHICS_COMPOSER_CALLBACK_H | ||
diff --git a/graphics/composer/2.1/vts/functional/TestCommandReader.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h index ae25d2d6..3888eebe 100644 --- a/graphics/composer/2.1/vts/functional/TestCommandReader.h +++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h | |||
@@ -14,8 +14,7 @@ | |||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifndef TEST_COMMAND_READER_H | 17 | #pragma once |
18 | #define TEST_COMMAND_READER_H | ||
19 | 18 | ||
20 | #include <composer-command-buffer/2.1/ComposerCommandBuffer.h> | 19 | #include <composer-command-buffer/2.1/ComposerCommandBuffer.h> |
21 | 20 | ||
@@ -24,22 +23,20 @@ namespace hardware { | |||
24 | namespace graphics { | 23 | namespace graphics { |
25 | namespace composer { | 24 | namespace composer { |
26 | namespace V2_1 { | 25 | namespace V2_1 { |
27 | namespace tests { | 26 | namespace vts { |
28 | 27 | ||
29 | // A command parser that checks that no error nor unexpected commands are | 28 | // A command parser that checks that no error nor unexpected commands are |
30 | // returned. | 29 | // returned. |
31 | class TestCommandReader : public CommandReaderBase { | 30 | class TestCommandReader : public CommandReaderBase { |
32 | public: | 31 | public: |
33 | // Parse all commands in the return command queue. Call GTEST_FAIL() for | 32 | // Parse all commands in the return command queue. Call GTEST_FAIL() for |
34 | // unexpected errors or commands. | 33 | // unexpected errors or commands. |
35 | void parse(); | 34 | void parse(); |
36 | }; | 35 | }; |
37 | 36 | ||
38 | } // namespace tests | 37 | } // namespace vts |
39 | } // namespace V2_1 | 38 | } // namespace V2_1 |
40 | } // namespace composer | 39 | } // namespace composer |
41 | } // namespace graphics | 40 | } // namespace graphics |
42 | } // namespace hardware | 41 | } // namespace hardware |
43 | } // namespace android | 42 | } // namespace android |
44 | |||
45 | #endif // TEST_COMMAND_READER_H | ||
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp index 92b65a36..8e346df9 100644 --- a/graphics/composer/2.1/vts/functional/Android.bp +++ b/graphics/composer/2.1/vts/functional/Android.bp | |||
@@ -14,36 +14,6 @@ | |||
14 | // limitations under the License. | 14 | // limitations under the License. |
15 | // | 15 | // |
16 | 16 | ||
17 | cc_library_static { | ||
18 | name: "libVtsHalGraphicsComposerTestUtils", | ||
19 | defaults: ["hidl_defaults"], | ||
20 | srcs: [ | ||
21 | "GraphicsComposerCallback.cpp", | ||
22 | "TestCommandReader.cpp", | ||
23 | "VtsHalGraphicsComposerTestUtils.cpp", | ||
24 | ], | ||
25 | shared_libs: [ | ||
26 | "android.hardware.graphics.composer@2.1", | ||
27 | "libfmq", | ||
28 | "libsync", | ||
29 | ], | ||
30 | static_libs: [ | ||
31 | "VtsHalHidlTargetTestBase", | ||
32 | ], | ||
33 | header_libs: [ | ||
34 | "android.hardware.graphics.composer@2.1-command-buffer", | ||
35 | ], | ||
36 | cflags: [ | ||
37 | "-Wall", | ||
38 | "-Wextra", | ||
39 | "-Werror", | ||
40 | "-O0", | ||
41 | "-g", | ||
42 | "-DLOG_TAG=\"GraphicsComposerTestUtils\"", | ||
43 | ], | ||
44 | export_include_dirs: ["."], | ||
45 | } | ||
46 | |||
47 | cc_test { | 17 | cc_test { |
48 | name: "VtsHalGraphicsComposerV2_1TargetTest", | 18 | name: "VtsHalGraphicsComposerV2_1TargetTest", |
49 | defaults: ["VtsHalTargetTestDefaults"], | 19 | defaults: ["VtsHalTargetTestDefaults"], |
@@ -57,10 +27,9 @@ cc_test { | |||
57 | static_libs: [ | 27 | static_libs: [ |
58 | "android.hardware.graphics.allocator@2.0", | 28 | "android.hardware.graphics.allocator@2.0", |
59 | "android.hardware.graphics.composer@2.1", | 29 | "android.hardware.graphics.composer@2.1", |
30 | "android.hardware.graphics.composer@2.1-vts", | ||
60 | "android.hardware.graphics.mapper@2.0", | 31 | "android.hardware.graphics.mapper@2.0", |
61 | "android.hardware.graphics.mapper@2.0-vts", | 32 | "android.hardware.graphics.mapper@2.0-vts", |
62 | "libVtsHalGraphicsComposerTestUtils", | ||
63 | "libnativehelper", | ||
64 | ], | 33 | ], |
65 | header_libs: [ | 34 | header_libs: [ |
66 | "android.hardware.graphics.composer@2.1-command-buffer", | 35 | "android.hardware.graphics.composer@2.1-command-buffer", |
diff --git a/graphics/composer/2.1/vts/functional/TestCommandReader.cpp b/graphics/composer/2.1/vts/functional/TestCommandReader.cpp deleted file mode 100644 index b1f9aca5..00000000 --- a/graphics/composer/2.1/vts/functional/TestCommandReader.cpp +++ /dev/null | |||
@@ -1,62 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include "TestCommandReader.h" | ||
18 | |||
19 | #include <gtest/gtest.h> | ||
20 | |||
21 | namespace android { | ||
22 | namespace hardware { | ||
23 | namespace graphics { | ||
24 | namespace composer { | ||
25 | namespace V2_1 { | ||
26 | namespace tests { | ||
27 | |||
28 | void TestCommandReader::parse() { | ||
29 | while (!isEmpty()) { | ||
30 | IComposerClient::Command command; | ||
31 | uint16_t length; | ||
32 | ASSERT_TRUE(beginCommand(&command, &length)); | ||
33 | |||
34 | switch (command) { | ||
35 | case IComposerClient::Command::SET_ERROR: { | ||
36 | ASSERT_EQ(2, length); | ||
37 | auto loc = read(); | ||
38 | auto err = readSigned(); | ||
39 | GTEST_FAIL() << "unexpected error " << err << " at location " << loc; | ||
40 | } break; | ||
41 | case IComposerClient::Command::SELECT_DISPLAY: | ||
42 | case IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES: | ||
43 | case IComposerClient::Command::SET_DISPLAY_REQUESTS: | ||
44 | case IComposerClient::Command::SET_PRESENT_FENCE: | ||
45 | case IComposerClient::Command::SET_RELEASE_FENCES: | ||
46 | break; | ||
47 | default: | ||
48 | GTEST_FAIL() << "unexpected return command " << std::hex | ||
49 | << static_cast<int>(command); | ||
50 | break; | ||
51 | } | ||
52 | |||
53 | endCommand(); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | } // namespace tests | ||
58 | } // namespace V2_1 | ||
59 | } // namespace composer | ||
60 | } // namespace graphics | ||
61 | } // namespace hardware | ||
62 | } // namespace android | ||
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.cpp deleted file mode 100644 index c66cdd0c..00000000 --- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.cpp +++ /dev/null | |||
@@ -1,345 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include <VtsHalHidlTargetTestBase.h> | ||
18 | |||
19 | #include "VtsHalGraphicsComposerTestUtils.h" | ||
20 | |||
21 | namespace android { | ||
22 | namespace hardware { | ||
23 | namespace graphics { | ||
24 | namespace composer { | ||
25 | namespace V2_1 { | ||
26 | namespace tests { | ||
27 | |||
28 | Composer::Composer() { | ||
29 | mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>(); | ||
30 | init(); | ||
31 | } | ||
32 | |||
33 | Composer::Composer(const std::string& name) { | ||
34 | mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>(name); | ||
35 | init(); | ||
36 | } | ||
37 | |||
38 | void Composer::init() { | ||
39 | ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service"; | ||
40 | |||
41 | std::vector<IComposer::Capability> capabilities = getCapabilities(); | ||
42 | mCapabilities.insert(capabilities.begin(), capabilities.end()); | ||
43 | } | ||
44 | |||
45 | sp<IComposer> Composer::getRaw() const { return mComposer; } | ||
46 | |||
47 | bool Composer::hasCapability(IComposer::Capability capability) const { | ||
48 | return mCapabilities.count(capability) > 0; | ||
49 | } | ||
50 | |||
51 | std::vector<IComposer::Capability> Composer::getCapabilities() { | ||
52 | std::vector<IComposer::Capability> capabilities; | ||
53 | mComposer->getCapabilities( | ||
54 | [&](const auto& tmpCapabilities) { capabilities = tmpCapabilities; }); | ||
55 | |||
56 | return capabilities; | ||
57 | } | ||
58 | |||
59 | std::string Composer::dumpDebugInfo() { | ||
60 | std::string debugInfo; | ||
61 | mComposer->dumpDebugInfo( | ||
62 | [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); }); | ||
63 | |||
64 | return debugInfo; | ||
65 | } | ||
66 | |||
67 | std::unique_ptr<ComposerClient> Composer::createClient() { | ||
68 | std::unique_ptr<ComposerClient> client; | ||
69 | mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) { | ||
70 | ASSERT_EQ(Error::NONE, tmpError) << "failed to create client"; | ||
71 | client = std::make_unique<ComposerClient>(tmpClient); | ||
72 | }); | ||
73 | |||
74 | return client; | ||
75 | } | ||
76 | |||
77 | ComposerClient::ComposerClient(const sp<IComposerClient>& client) | ||
78 | : mClient(client) {} | ||
79 | |||
80 | ComposerClient::~ComposerClient() { | ||
81 | for (auto it : mDisplayResources) { | ||
82 | Display display = it.first; | ||
83 | DisplayResource& resource = it.second; | ||
84 | |||
85 | for (auto layer : resource.layers) { | ||
86 | EXPECT_EQ(Error::NONE, mClient->destroyLayer(display, layer)) | ||
87 | << "failed to destroy layer " << layer; | ||
88 | } | ||
89 | |||
90 | if (resource.isVirtual) { | ||
91 | EXPECT_EQ(Error::NONE, mClient->destroyVirtualDisplay(display)) | ||
92 | << "failed to destroy virtual display " << display; | ||
93 | } | ||
94 | } | ||
95 | mDisplayResources.clear(); | ||
96 | } | ||
97 | |||
98 | sp<IComposerClient> ComposerClient::getRaw() const { return mClient; } | ||
99 | |||
100 | void ComposerClient::registerCallback(const sp<IComposerCallback>& callback) { | ||
101 | mClient->registerCallback(callback); | ||
102 | } | ||
103 | |||
104 | uint32_t ComposerClient::getMaxVirtualDisplayCount() { | ||
105 | return mClient->getMaxVirtualDisplayCount(); | ||
106 | } | ||
107 | |||
108 | Display ComposerClient::createVirtualDisplay(uint32_t width, uint32_t height, | ||
109 | PixelFormat formatHint, | ||
110 | uint32_t outputBufferSlotCount, | ||
111 | PixelFormat* outFormat) { | ||
112 | Display display = 0; | ||
113 | mClient->createVirtualDisplay( | ||
114 | width, height, formatHint, outputBufferSlotCount, | ||
115 | [&](const auto& tmpError, const auto& tmpDisplay, const auto& tmpFormat) { | ||
116 | ASSERT_EQ(Error::NONE, tmpError) << "failed to create virtual display"; | ||
117 | display = tmpDisplay; | ||
118 | *outFormat = tmpFormat; | ||
119 | |||
120 | ASSERT_TRUE( | ||
121 | mDisplayResources.insert({display, DisplayResource(true)}).second) | ||
122 | << "duplicated virtual display id " << display; | ||
123 | }); | ||
124 | |||
125 | return display; | ||
126 | } | ||
127 | |||
128 | void ComposerClient::destroyVirtualDisplay(Display display) { | ||
129 | Error error = mClient->destroyVirtualDisplay(display); | ||
130 | ASSERT_EQ(Error::NONE, error) | ||
131 | << "failed to destroy virtual display " << display; | ||
132 | |||
133 | mDisplayResources.erase(display); | ||
134 | } | ||
135 | |||
136 | Layer ComposerClient::createLayer(Display display, uint32_t bufferSlotCount) { | ||
137 | Layer layer = 0; | ||
138 | mClient->createLayer( | ||
139 | display, bufferSlotCount, | ||
140 | [&](const auto& tmpError, const auto& tmpLayer) { | ||
141 | ASSERT_EQ(Error::NONE, tmpError) << "failed to create layer"; | ||
142 | layer = tmpLayer; | ||
143 | |||
144 | auto resourceIt = mDisplayResources.find(display); | ||
145 | if (resourceIt == mDisplayResources.end()) { | ||
146 | resourceIt = | ||
147 | mDisplayResources.insert({display, DisplayResource(false)}).first; | ||
148 | } | ||
149 | |||
150 | ASSERT_TRUE(resourceIt->second.layers.insert(layer).second) | ||
151 | << "duplicated layer id " << layer; | ||
152 | }); | ||
153 | |||
154 | return layer; | ||
155 | } | ||
156 | |||
157 | void ComposerClient::destroyLayer(Display display, Layer layer) { | ||
158 | Error error = mClient->destroyLayer(display, layer); | ||
159 | ASSERT_EQ(Error::NONE, error) << "failed to destroy layer " << layer; | ||
160 | |||
161 | auto resourceIt = mDisplayResources.find(display); | ||
162 | ASSERT_NE(mDisplayResources.end(), resourceIt); | ||
163 | resourceIt->second.layers.erase(layer); | ||
164 | } | ||
165 | |||
166 | Config ComposerClient::getActiveConfig(Display display) { | ||
167 | Config config = 0; | ||
168 | mClient->getActiveConfig( | ||
169 | display, [&](const auto& tmpError, const auto& tmpConfig) { | ||
170 | ASSERT_EQ(Error::NONE, tmpError) << "failed to get active config"; | ||
171 | config = tmpConfig; | ||
172 | }); | ||
173 | |||
174 | return config; | ||
175 | } | ||
176 | |||
177 | bool ComposerClient::getClientTargetSupport(Display display, uint32_t width, | ||
178 | uint32_t height, PixelFormat format, | ||
179 | Dataspace dataspace) { | ||
180 | Error error = mClient->getClientTargetSupport(display, width, height, format, | ||
181 | dataspace); | ||
182 | return error == Error::NONE; | ||
183 | } | ||
184 | |||
185 | std::vector<ColorMode> ComposerClient::getColorModes(Display display) { | ||
186 | std::vector<ColorMode> modes; | ||
187 | mClient->getColorModes( | ||
188 | display, [&](const auto& tmpError, const auto& tmpMode) { | ||
189 | ASSERT_EQ(Error::NONE, tmpError) << "failed to get color mode"; | ||
190 | modes = tmpMode; | ||
191 | }); | ||
192 | |||
193 | return modes; | ||
194 | } | ||
195 | |||
196 | int32_t ComposerClient::getDisplayAttribute( | ||
197 | Display display, Config config, IComposerClient::Attribute attribute) { | ||
198 | int32_t value = 0; | ||
199 | mClient->getDisplayAttribute(display, config, attribute, | ||
200 | [&](const auto& tmpError, const auto& tmpValue) { | ||
201 | ASSERT_EQ(Error::NONE, tmpError) | ||
202 | << "failed to get display attribute"; | ||
203 | value = tmpValue; | ||
204 | }); | ||
205 | |||
206 | return value; | ||
207 | } | ||
208 | |||
209 | std::vector<Config> ComposerClient::getDisplayConfigs(Display display) { | ||
210 | std::vector<Config> configs; | ||
211 | mClient->getDisplayConfigs( | ||
212 | display, [&](const auto& tmpError, const auto& tmpConfigs) { | ||
213 | ASSERT_EQ(Error::NONE, tmpError) << "failed to get display configs"; | ||
214 | configs = tmpConfigs; | ||
215 | }); | ||
216 | |||
217 | return configs; | ||
218 | } | ||
219 | |||
220 | std::string ComposerClient::getDisplayName(Display display) { | ||
221 | std::string name; | ||
222 | mClient->getDisplayName( | ||
223 | display, [&](const auto& tmpError, const auto& tmpName) { | ||
224 | ASSERT_EQ(Error::NONE, tmpError) << "failed to get display name"; | ||
225 | name = tmpName.c_str(); | ||
226 | }); | ||
227 | |||
228 | return name; | ||
229 | } | ||
230 | |||
231 | IComposerClient::DisplayType ComposerClient::getDisplayType(Display display) { | ||
232 | IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID; | ||
233 | mClient->getDisplayType( | ||
234 | display, [&](const auto& tmpError, const auto& tmpType) { | ||
235 | ASSERT_EQ(Error::NONE, tmpError) << "failed to get display type"; | ||
236 | type = tmpType; | ||
237 | }); | ||
238 | |||
239 | return type; | ||
240 | } | ||
241 | |||
242 | bool ComposerClient::getDozeSupport(Display display) { | ||
243 | bool support = false; | ||
244 | mClient->getDozeSupport( | ||
245 | display, [&](const auto& tmpError, const auto& tmpSupport) { | ||
246 | ASSERT_EQ(Error::NONE, tmpError) << "failed to get doze support"; | ||
247 | support = tmpSupport; | ||
248 | }); | ||
249 | |||
250 | return support; | ||
251 | } | ||
252 | |||
253 | std::vector<Hdr> ComposerClient::getHdrCapabilities( | ||
254 | Display display, float* outMaxLuminance, float* outMaxAverageLuminance, | ||
255 | float* outMinLuminance) { | ||
256 | std::vector<Hdr> types; | ||
257 | mClient->getHdrCapabilities( | ||
258 | display, | ||
259 | [&](const auto& tmpError, const auto& tmpTypes, | ||
260 | const auto& tmpMaxLuminance, const auto& tmpMaxAverageLuminance, | ||
261 | const auto& tmpMinLuminance) { | ||
262 | ASSERT_EQ(Error::NONE, tmpError) << "failed to get HDR capabilities"; | ||
263 | types = tmpTypes; | ||
264 | *outMaxLuminance = tmpMaxLuminance; | ||
265 | *outMaxAverageLuminance = tmpMaxAverageLuminance; | ||
266 | *outMinLuminance = tmpMinLuminance; | ||
267 | }); | ||
268 | |||
269 | return types; | ||
270 | } | ||
271 | |||
272 | void ComposerClient::setClientTargetSlotCount(Display display, | ||
273 | uint32_t clientTargetSlotCount) { | ||
274 | Error error = | ||
275 | mClient->setClientTargetSlotCount(display, clientTargetSlotCount); | ||
276 | ASSERT_EQ(Error::NONE, error) << "failed to set client target slot count"; | ||
277 | } | ||
278 | |||
279 | void ComposerClient::setActiveConfig(Display display, Config config) { | ||
280 | Error error = mClient->setActiveConfig(display, config); | ||
281 | ASSERT_EQ(Error::NONE, error) << "failed to set active config"; | ||
282 | } | ||
283 | |||
284 | void ComposerClient::setColorMode(Display display, ColorMode mode) { | ||
285 | Error error = mClient->setColorMode(display, mode); | ||
286 | ASSERT_EQ(Error::NONE, error) << "failed to set color mode"; | ||
287 | } | ||
288 | |||
289 | void ComposerClient::setPowerMode(Display display, | ||
290 | IComposerClient::PowerMode mode) { | ||
291 | Error error = mClient->setPowerMode(display, mode); | ||
292 | ASSERT_EQ(Error::NONE, error) << "failed to set power mode"; | ||
293 | } | ||
294 | |||
295 | void ComposerClient::setVsyncEnabled(Display display, bool enabled) { | ||
296 | IComposerClient::Vsync vsync = (enabled) ? IComposerClient::Vsync::ENABLE | ||
297 | : IComposerClient::Vsync::DISABLE; | ||
298 | Error error = mClient->setVsyncEnabled(display, vsync); | ||
299 | ASSERT_EQ(Error::NONE, error) << "failed to set vsync mode"; | ||
300 | |||
301 | // give the hwbinder thread some time to handle any pending vsync callback | ||
302 | if (!enabled) { | ||
303 | usleep(5 * 1000); | ||
304 | } | ||
305 | } | ||
306 | |||
307 | void ComposerClient::execute(TestCommandReader* reader, | ||
308 | CommandWriterBase* writer) { | ||
309 | bool queueChanged = false; | ||
310 | uint32_t commandLength = 0; | ||
311 | hidl_vec<hidl_handle> commandHandles; | ||
312 | ASSERT_TRUE( | ||
313 | writer->writeQueue(&queueChanged, &commandLength, &commandHandles)); | ||
314 | |||
315 | if (queueChanged) { | ||
316 | auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor()); | ||
317 | ASSERT_EQ(Error::NONE, static_cast<Error>(ret)); | ||
318 | return; | ||
319 | } | ||
320 | |||
321 | mClient->executeCommands( | ||
322 | commandLength, commandHandles, | ||
323 | [&](const auto& tmpError, const auto& tmpOutQueueChanged, | ||
324 | const auto& tmpOutLength, const auto& tmpOutHandles) { | ||
325 | ASSERT_EQ(Error::NONE, tmpError); | ||
326 | |||
327 | if (tmpOutQueueChanged) { | ||
328 | mClient->getOutputCommandQueue( | ||
329 | [&](const auto& tmpError, const auto& tmpDescriptor) { | ||
330 | ASSERT_EQ(Error::NONE, tmpError); | ||
331 | reader->setMQDescriptor(tmpDescriptor); | ||
332 | }); | ||
333 | } | ||
334 | |||
335 | ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles)); | ||
336 | reader->parse(); | ||
337 | }); | ||
338 | } | ||
339 | |||
340 | } // namespace tests | ||
341 | } // namespace V2_1 | ||
342 | } // namespace composer | ||
343 | } // namespace graphics | ||
344 | } // namespace hardware | ||
345 | } // namespace android | ||
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h deleted file mode 100644 index 00d9d8c9..00000000 --- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h +++ /dev/null | |||
@@ -1,134 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef VTS_HAL_GRAPHICS_COMPOSER_UTILS | ||
18 | #define VTS_HAL_GRAPHICS_COMPOSER_UTILS | ||
19 | |||
20 | #include <memory> | ||
21 | #include <string> | ||
22 | #include <unordered_map> | ||
23 | #include <unordered_set> | ||
24 | #include <vector> | ||
25 | |||
26 | #include <android/hardware/graphics/composer/2.1/IComposer.h> | ||
27 | #include <composer-command-buffer/2.1/ComposerCommandBuffer.h> | ||
28 | #include <utils/StrongPointer.h> | ||
29 | |||
30 | #include "TestCommandReader.h" | ||
31 | |||
32 | namespace android { | ||
33 | namespace hardware { | ||
34 | namespace graphics { | ||
35 | namespace composer { | ||
36 | namespace V2_1 { | ||
37 | namespace tests { | ||
38 | |||
39 | using android::hardware::graphics::common::V1_0::ColorMode; | ||
40 | using android::hardware::graphics::common::V1_0::Dataspace; | ||
41 | using android::hardware::graphics::common::V1_0::Hdr; | ||
42 | using android::hardware::graphics::common::V1_0::PixelFormat; | ||
43 | |||
44 | class ComposerClient; | ||
45 | |||
46 | // A wrapper to IComposer. | ||
47 | class Composer { | ||
48 | public: | ||
49 | Composer(); | ||
50 | explicit Composer(const std::string& name); | ||
51 | |||
52 | sp<IComposer> getRaw() const; | ||
53 | |||
54 | // Returns true when the composer supports the specified capability. | ||
55 | bool hasCapability(IComposer::Capability capability) const; | ||
56 | |||
57 | std::vector<IComposer::Capability> getCapabilities(); | ||
58 | std::string dumpDebugInfo(); | ||
59 | std::unique_ptr<ComposerClient> createClient(); | ||
60 | |||
61 | protected: | ||
62 | sp<IComposer> mComposer; | ||
63 | |||
64 | private: | ||
65 | void init(); | ||
66 | |||
67 | std::unordered_set<IComposer::Capability> mCapabilities; | ||
68 | }; | ||
69 | |||
70 | // A wrapper to IComposerClient. | ||
71 | class ComposerClient { | ||
72 | public: | ||
73 | ComposerClient(const sp<IComposerClient>& client); | ||
74 | ~ComposerClient(); | ||
75 | |||
76 | sp<IComposerClient> getRaw() const; | ||
77 | |||
78 | void registerCallback(const sp<IComposerCallback>& callback); | ||
79 | uint32_t getMaxVirtualDisplayCount(); | ||
80 | |||
81 | Display createVirtualDisplay(uint32_t width, uint32_t height, | ||
82 | PixelFormat formatHint, | ||
83 | uint32_t outputBufferSlotCount, | ||
84 | PixelFormat* outFormat); | ||
85 | void destroyVirtualDisplay(Display display); | ||
86 | |||
87 | Layer createLayer(Display display, uint32_t bufferSlotCount); | ||
88 | void destroyLayer(Display display, Layer layer); | ||
89 | |||
90 | Config getActiveConfig(Display display); | ||
91 | bool getClientTargetSupport(Display display, uint32_t width, uint32_t height, | ||
92 | PixelFormat format, Dataspace dataspace); | ||
93 | std::vector<ColorMode> getColorModes(Display display); | ||
94 | int32_t getDisplayAttribute(Display display, Config config, | ||
95 | IComposerClient::Attribute attribute); | ||
96 | std::vector<Config> getDisplayConfigs(Display display); | ||
97 | std::string getDisplayName(Display display); | ||
98 | IComposerClient::DisplayType getDisplayType(Display display); | ||
99 | bool getDozeSupport(Display display); | ||
100 | std::vector<Hdr> getHdrCapabilities(Display display, float* outMaxLuminance, | ||
101 | float* outMaxAverageLuminance, | ||
102 | float* outMinLuminance); | ||
103 | |||
104 | void setClientTargetSlotCount(Display display, | ||
105 | uint32_t clientTargetSlotCount); | ||
106 | void setActiveConfig(Display display, Config config); | ||
107 | void setColorMode(Display display, ColorMode mode); | ||
108 | void setPowerMode(Display display, IComposerClient::PowerMode mode); | ||
109 | void setVsyncEnabled(Display display, bool enabled); | ||
110 | |||
111 | void execute(TestCommandReader* reader, CommandWriterBase* writer); | ||
112 | |||
113 | private: | ||
114 | sp<IComposerClient> mClient; | ||
115 | |||
116 | // Keep track of all virtual displays and layers. When a test fails with | ||
117 | // ASSERT_*, the destructor will clean up the resources for the test. | ||
118 | struct DisplayResource { | ||
119 | DisplayResource(bool isVirtual_) : isVirtual(isVirtual_) {} | ||
120 | |||
121 | bool isVirtual; | ||
122 | std::unordered_set<Layer> layers; | ||
123 | }; | ||
124 | std::unordered_map<Display, DisplayResource> mDisplayResources; | ||
125 | }; | ||
126 | |||
127 | } // namespace tests | ||
128 | } // namespace V2_1 | ||
129 | } // namespace composer | ||
130 | } // namespace graphics | ||
131 | } // namespace hardware | ||
132 | } // namespace android | ||
133 | |||
134 | #endif // VTS_HAL_GRAPHICS_COMPOSER_UTILS | ||
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp index 376ee379..8b8b530a 100644 --- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp +++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp | |||
@@ -17,10 +17,10 @@ | |||
17 | #define LOG_TAG "graphics_composer_hidl_hal_test" | 17 | #define LOG_TAG "graphics_composer_hidl_hal_test" |
18 | 18 | ||
19 | #include <android-base/logging.h> | 19 | #include <android-base/logging.h> |
20 | #include <composer-vts/2.1/ComposerVts.h> | ||
21 | #include <composer-vts/2.1/GraphicsComposerCallback.h> | ||
22 | #include <composer-vts/2.1/TestCommandReader.h> | ||
20 | #include <mapper-vts/2.0/MapperVts.h> | 23 | #include <mapper-vts/2.0/MapperVts.h> |
21 | #include "GraphicsComposerCallback.h" | ||
22 | #include "TestCommandReader.h" | ||
23 | #include "VtsHalGraphicsComposerTestUtils.h" | ||
24 | 24 | ||
25 | #include <VtsHalHidlTargetTestBase.h> | 25 | #include <VtsHalHidlTargetTestBase.h> |
26 | #include <VtsHalHidlTargetTestEnvBase.h> | 26 | #include <VtsHalHidlTargetTestEnvBase.h> |
@@ -38,7 +38,7 @@ namespace hardware { | |||
38 | namespace graphics { | 38 | namespace graphics { |
39 | namespace composer { | 39 | namespace composer { |
40 | namespace V2_1 { | 40 | namespace V2_1 { |
41 | namespace tests { | 41 | namespace vts { |
42 | namespace { | 42 | namespace { |
43 | 43 | ||
44 | using android::hardware::graphics::common::V1_0::BufferUsage; | 44 | using android::hardware::graphics::common::V1_0::BufferUsage; |
@@ -69,53 +69,53 @@ class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEn | |||
69 | }; | 69 | }; |
70 | 70 | ||
71 | class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { | 71 | class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { |
72 | protected: | 72 | protected: |
73 | void SetUp() override { | 73 | void SetUp() override { |
74 | ASSERT_NO_FATAL_FAILURE( | 74 | ASSERT_NO_FATAL_FAILURE( |
75 | mComposer = std::make_unique<Composer>( | 75 | mComposer = std::make_unique<Composer>( |
76 | GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>())); | 76 | GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>())); |
77 | ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient()); | 77 | ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient()); |
78 | 78 | ||
79 | mComposerCallback = new GraphicsComposerCallback; | 79 | mComposerCallback = new GraphicsComposerCallback; |
80 | mComposerClient->registerCallback(mComposerCallback); | 80 | mComposerClient->registerCallback(mComposerCallback); |
81 | 81 | ||
82 | // assume the first display is primary and is never removed | 82 | // assume the first display is primary and is never removed |
83 | mPrimaryDisplay = waitForFirstDisplay(); | 83 | mPrimaryDisplay = waitForFirstDisplay(); |
84 | 84 | ||
85 | // explicitly disable vsync | 85 | // explicitly disable vsync |
86 | mComposerClient->setVsyncEnabled(mPrimaryDisplay, false); | 86 | mComposerClient->setVsyncEnabled(mPrimaryDisplay, false); |
87 | mComposerCallback->setVsyncAllowed(false); | 87 | mComposerCallback->setVsyncAllowed(false); |
88 | } | ||
89 | |||
90 | void TearDown() override { | ||
91 | if (mComposerCallback != nullptr) { | ||
92 | EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount()); | ||
93 | EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount()); | ||
94 | EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount()); | ||
95 | } | 88 | } |
96 | } | 89 | |
97 | 90 | void TearDown() override { | |
98 | // use the slot count usually set by SF | 91 | if (mComposerCallback != nullptr) { |
99 | static constexpr uint32_t kBufferSlotCount = 64; | 92 | EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount()); |
100 | 93 | EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount()); | |
101 | std::unique_ptr<Composer> mComposer; | 94 | EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount()); |
102 | std::unique_ptr<ComposerClient> mComposerClient; | 95 | } |
103 | sp<GraphicsComposerCallback> mComposerCallback; | 96 | } |
104 | // the first display and is assumed never to be removed | 97 | |
105 | Display mPrimaryDisplay; | 98 | // use the slot count usually set by SF |
106 | 99 | static constexpr uint32_t kBufferSlotCount = 64; | |
107 | private: | 100 | |
108 | Display waitForFirstDisplay() { | 101 | std::unique_ptr<Composer> mComposer; |
109 | while (true) { | 102 | std::unique_ptr<ComposerClient> mComposerClient; |
110 | std::vector<Display> displays = mComposerCallback->getDisplays(); | 103 | sp<GraphicsComposerCallback> mComposerCallback; |
111 | if (displays.empty()) { | 104 | // the first display and is assumed never to be removed |
112 | usleep(5 * 1000); | 105 | Display mPrimaryDisplay; |
113 | continue; | 106 | |
114 | } | 107 | private: |
115 | 108 | Display waitForFirstDisplay() { | |
116 | return displays[0]; | 109 | while (true) { |
110 | std::vector<Display> displays = mComposerCallback->getDisplays(); | ||
111 | if (displays.empty()) { | ||
112 | usleep(5 * 1000); | ||
113 | continue; | ||
114 | } | ||
115 | |||
116 | return displays[0]; | ||
117 | } | ||
117 | } | 118 | } |
118 | } | ||
119 | }; | 119 | }; |
120 | 120 | ||
121 | /** | 121 | /** |
@@ -124,16 +124,17 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { | |||
124 | * Test that IComposer::getCapabilities returns no invalid capabilities. | 124 | * Test that IComposer::getCapabilities returns no invalid capabilities. |
125 | */ | 125 | */ |
126 | TEST_F(GraphicsComposerHidlTest, GetCapabilities) { | 126 | TEST_F(GraphicsComposerHidlTest, GetCapabilities) { |
127 | auto capabilities = mComposer->getCapabilities(); | 127 | auto capabilities = mComposer->getCapabilities(); |
128 | ASSERT_EQ(capabilities.end(), | 128 | ASSERT_EQ(capabilities.end(), |
129 | std::find(capabilities.begin(), capabilities.end(), | 129 | std::find(capabilities.begin(), capabilities.end(), IComposer::Capability::INVALID)); |
130 | IComposer::Capability::INVALID)); | ||
131 | } | 130 | } |
132 | 131 | ||
133 | /** | 132 | /** |
134 | * Test IComposer::dumpDebugInfo. | 133 | * Test IComposer::dumpDebugInfo. |
135 | */ | 134 | */ |
136 | TEST_F(GraphicsComposerHidlTest, DumpDebugInfo) { mComposer->dumpDebugInfo(); } | 135 | TEST_F(GraphicsComposerHidlTest, DumpDebugInfo) { |
136 | mComposer->dumpDebugInfo(); | ||
137 | } | ||
137 | 138 | ||
138 | /** | 139 | /** |
139 | * Test IComposer::createClient. | 140 | * Test IComposer::createClient. |
@@ -141,9 +142,8 @@ TEST_F(GraphicsComposerHidlTest, DumpDebugInfo) { mComposer->dumpDebugInfo(); } | |||
141 | * Test that IComposerClient is a singleton. | 142 | * Test that IComposerClient is a singleton. |
142 | */ | 143 | */ |
143 | TEST_F(GraphicsComposerHidlTest, CreateClientSingleton) { | 144 | TEST_F(GraphicsComposerHidlTest, CreateClientSingleton) { |
144 | mComposer->getRaw()->createClient([&](const auto& tmpError, const auto&) { | 145 | mComposer->getRaw()->createClient( |
145 | EXPECT_EQ(Error::NO_RESOURCES, tmpError); | 146 | [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::NO_RESOURCES, tmpError); }); |
146 | }); | ||
147 | } | 147 | } |
148 | 148 | ||
149 | /** | 149 | /** |
@@ -153,22 +153,22 @@ TEST_F(GraphicsComposerHidlTest, CreateClientSingleton) { | |||
153 | * Test that virtual displays can be created and has the correct display type. | 153 | * Test that virtual displays can be created and has the correct display type. |
154 | */ | 154 | */ |
155 | TEST_F(GraphicsComposerHidlTest, CreateVirtualDisplay) { | 155 | TEST_F(GraphicsComposerHidlTest, CreateVirtualDisplay) { |
156 | if (mComposerClient->getMaxVirtualDisplayCount() == 0) { | 156 | if (mComposerClient->getMaxVirtualDisplayCount() == 0) { |
157 | GTEST_SUCCEED() << "no virtual display support"; | 157 | GTEST_SUCCEED() << "no virtual display support"; |
158 | return; | 158 | return; |
159 | } | 159 | } |
160 | 160 | ||
161 | Display display; | 161 | Display display; |
162 | PixelFormat format; | 162 | PixelFormat format; |
163 | ASSERT_NO_FATAL_FAILURE(display = mComposerClient->createVirtualDisplay( | 163 | ASSERT_NO_FATAL_FAILURE( |
164 | 64, 64, PixelFormat::IMPLEMENTATION_DEFINED, | 164 | display = mComposerClient->createVirtualDisplay(64, 64, PixelFormat::IMPLEMENTATION_DEFINED, |
165 | kBufferSlotCount, &format)); | 165 | kBufferSlotCount, &format)); |
166 | 166 | ||
167 | // test display type | 167 | // test display type |
168 | IComposerClient::DisplayType type = mComposerClient->getDisplayType(display); | 168 | IComposerClient::DisplayType type = mComposerClient->getDisplayType(display); |
169 | EXPECT_EQ(IComposerClient::DisplayType::VIRTUAL, type); | 169 | EXPECT_EQ(IComposerClient::DisplayType::VIRTUAL, type); |
170 | 170 | ||
171 | mComposerClient->destroyVirtualDisplay(display); | 171 | mComposerClient->destroyVirtualDisplay(display); |
172 | } | 172 | } |
173 | 173 | ||
174 | /** | 174 | /** |
@@ -177,18 +177,18 @@ TEST_F(GraphicsComposerHidlTest, CreateVirtualDisplay) { | |||
177 | * Test that layers can be created and destroyed. | 177 | * Test that layers can be created and destroyed. |
178 | */ | 178 | */ |
179 | TEST_F(GraphicsComposerHidlTest, CreateLayer) { | 179 | TEST_F(GraphicsComposerHidlTest, CreateLayer) { |
180 | Layer layer; | 180 | Layer layer; |
181 | ASSERT_NO_FATAL_FAILURE( | 181 | ASSERT_NO_FATAL_FAILURE(layer = |
182 | layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); | 182 | mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); |
183 | 183 | ||
184 | mComposerClient->destroyLayer(mPrimaryDisplay, layer); | 184 | mComposerClient->destroyLayer(mPrimaryDisplay, layer); |
185 | } | 185 | } |
186 | 186 | ||
187 | /** | 187 | /** |
188 | * Test IComposerClient::getDisplayName. | 188 | * Test IComposerClient::getDisplayName. |
189 | */ | 189 | */ |
190 | TEST_F(GraphicsComposerHidlTest, GetDisplayName) { | 190 | TEST_F(GraphicsComposerHidlTest, GetDisplayName) { |
191 | mComposerClient->getDisplayName(mPrimaryDisplay); | 191 | mComposerClient->getDisplayName(mPrimaryDisplay); |
192 | } | 192 | } |
193 | 193 | ||
194 | /** | 194 | /** |
@@ -198,8 +198,8 @@ TEST_F(GraphicsComposerHidlTest, GetDisplayName) { | |||
198 | * for the primary display. | 198 | * for the primary display. |
199 | */ | 199 | */ |
200 | TEST_F(GraphicsComposerHidlTest, GetDisplayType) { | 200 | TEST_F(GraphicsComposerHidlTest, GetDisplayType) { |
201 | ASSERT_EQ(IComposerClient::DisplayType::PHYSICAL, | 201 | ASSERT_EQ(IComposerClient::DisplayType::PHYSICAL, |
202 | mComposerClient->getDisplayType(mPrimaryDisplay)); | 202 | mComposerClient->getDisplayType(mPrimaryDisplay)); |
203 | } | 203 | } |
204 | 204 | ||
205 | /** | 205 | /** |
@@ -209,22 +209,20 @@ TEST_F(GraphicsComposerHidlTest, GetDisplayType) { | |||
209 | * required client targets. | 209 | * required client targets. |
210 | */ | 210 | */ |
211 | TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport) { | 211 | TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport) { |
212 | std::vector<Config> configs = | 212 | std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay); |
213 | mComposerClient->getDisplayConfigs(mPrimaryDisplay); | 213 | for (auto config : configs) { |
214 | for (auto config : configs) { | 214 | int32_t width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, |
215 | int32_t width = mComposerClient->getDisplayAttribute( | 215 | IComposerClient::Attribute::WIDTH); |
216 | mPrimaryDisplay, config, IComposerClient::Attribute::WIDTH); | 216 | int32_t height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, |
217 | int32_t height = mComposerClient->getDisplayAttribute( | 217 | IComposerClient::Attribute::HEIGHT); |
218 | mPrimaryDisplay, config, IComposerClient::Attribute::HEIGHT); | 218 | ASSERT_LT(0, width); |
219 | ASSERT_LT(0, width); | 219 | ASSERT_LT(0, height); |
220 | ASSERT_LT(0, height); | 220 | |
221 | 221 | mComposerClient->setActiveConfig(mPrimaryDisplay, config); | |
222 | mComposerClient->setActiveConfig(mPrimaryDisplay, config); | 222 | |
223 | 223 | ASSERT_TRUE(mComposerClient->getClientTargetSupport( | |
224 | ASSERT_TRUE(mComposerClient->getClientTargetSupport( | 224 | mPrimaryDisplay, width, height, PixelFormat::RGBA_8888, Dataspace::UNKNOWN)); |
225 | mPrimaryDisplay, width, height, PixelFormat::RGBA_8888, | 225 | } |
226 | Dataspace::UNKNOWN)); | ||
227 | } | ||
228 | } | 226 | } |
229 | 227 | ||
230 | /** | 228 | /** |
@@ -234,47 +232,44 @@ TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport) { | |||
234 | * formats, and succeeds or fails correctly for optional attributes. | 232 | * formats, and succeeds or fails correctly for optional attributes. |
235 | */ | 233 | */ |
236 | TEST_F(GraphicsComposerHidlTest, GetDisplayAttribute) { | 234 | TEST_F(GraphicsComposerHidlTest, GetDisplayAttribute) { |
237 | std::vector<Config> configs = | 235 | std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay); |
238 | mComposerClient->getDisplayConfigs(mPrimaryDisplay); | 236 | for (auto config : configs) { |
239 | for (auto config : configs) { | 237 | const std::array<IComposerClient::Attribute, 3> requiredAttributes = {{ |
240 | const std::array<IComposerClient::Attribute, 3> requiredAttributes = {{ | 238 | IComposerClient::Attribute::WIDTH, IComposerClient::Attribute::HEIGHT, |
241 | IComposerClient::Attribute::WIDTH, IComposerClient::Attribute::HEIGHT, | 239 | IComposerClient::Attribute::VSYNC_PERIOD, |
242 | IComposerClient::Attribute::VSYNC_PERIOD, | 240 | }}; |
243 | }}; | 241 | for (auto attribute : requiredAttributes) { |
244 | for (auto attribute : requiredAttributes) { | 242 | mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, attribute); |
245 | mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, attribute); | 243 | } |
246 | } | 244 | |
247 | 245 | const std::array<IComposerClient::Attribute, 2> optionalAttributes = {{ | |
248 | const std::array<IComposerClient::Attribute, 2> optionalAttributes = {{ | 246 | IComposerClient::Attribute::DPI_X, IComposerClient::Attribute::DPI_Y, |
249 | IComposerClient::Attribute::DPI_X, IComposerClient::Attribute::DPI_Y, | 247 | }}; |
250 | }}; | 248 | for (auto attribute : optionalAttributes) { |
251 | for (auto attribute : optionalAttributes) { | 249 | mComposerClient->getRaw()->getDisplayAttribute( |
252 | mComposerClient->getRaw()->getDisplayAttribute( | 250 | mPrimaryDisplay, config, attribute, [&](const auto& tmpError, const auto&) { |
253 | mPrimaryDisplay, config, attribute, | 251 | EXPECT_TRUE(tmpError == Error::NONE || tmpError == Error::UNSUPPORTED); |
254 | [&](const auto& tmpError, const auto&) { | 252 | }); |
255 | EXPECT_TRUE(tmpError == Error::NONE || | 253 | } |
256 | tmpError == Error::UNSUPPORTED); | ||
257 | }); | ||
258 | } | 254 | } |
259 | } | ||
260 | } | 255 | } |
261 | 256 | ||
262 | /** | 257 | /** |
263 | * Test IComposerClient::getHdrCapabilities. | 258 | * Test IComposerClient::getHdrCapabilities. |
264 | */ | 259 | */ |
265 | TEST_F(GraphicsComposerHidlTest, GetHdrCapabilities) { | 260 | TEST_F(GraphicsComposerHidlTest, GetHdrCapabilities) { |
266 | float maxLuminance; | 261 | float maxLuminance; |
267 | float maxAverageLuminance; | 262 | float maxAverageLuminance; |
268 | float minLuminance; | 263 | float minLuminance; |
269 | mComposerClient->getHdrCapabilities(mPrimaryDisplay, &maxLuminance, | 264 | mComposerClient->getHdrCapabilities(mPrimaryDisplay, &maxLuminance, &maxAverageLuminance, |
270 | &maxAverageLuminance, &minLuminance); | 265 | &minLuminance); |
271 | } | 266 | } |
272 | 267 | ||
273 | /** | 268 | /** |
274 | * Test IComposerClient::setClientTargetSlotCount. | 269 | * Test IComposerClient::setClientTargetSlotCount. |
275 | */ | 270 | */ |
276 | TEST_F(GraphicsComposerHidlTest, SetClientTargetSlotCount) { | 271 | TEST_F(GraphicsComposerHidlTest, SetClientTargetSlotCount) { |
277 | mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount); | 272 | mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount); |
278 | } | 273 | } |
279 | 274 | ||
280 | /** | 275 | /** |
@@ -284,12 +279,11 @@ TEST_F(GraphicsComposerHidlTest, SetClientTargetSlotCount) { | |||
284 | * configs. | 279 | * configs. |
285 | */ | 280 | */ |
286 | TEST_F(GraphicsComposerHidlTest, SetActiveConfig) { | 281 | TEST_F(GraphicsComposerHidlTest, SetActiveConfig) { |
287 | std::vector<Config> configs = | 282 | std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay); |
288 | mComposerClient->getDisplayConfigs(mPrimaryDisplay); | 283 | for (auto config : configs) { |
289 | for (auto config : configs) { | 284 | mComposerClient->setActiveConfig(mPrimaryDisplay, config); |
290 | mComposerClient->setActiveConfig(mPrimaryDisplay, config); | 285 | ASSERT_EQ(config, mComposerClient->getActiveConfig(mPrimaryDisplay)); |
291 | ASSERT_EQ(config, mComposerClient->getActiveConfig(mPrimaryDisplay)); | 286 | } |
292 | } | ||
293 | } | 287 | } |
294 | 288 | ||
295 | /** | 289 | /** |
@@ -298,11 +292,10 @@ TEST_F(GraphicsComposerHidlTest, SetActiveConfig) { | |||
298 | * Test that IComposerClient::setColorMode succeeds for all color modes. | 292 | * Test that IComposerClient::setColorMode succeeds for all color modes. |
299 | */ | 293 | */ |
300 | TEST_F(GraphicsComposerHidlTest, SetColorMode) { | 294 | TEST_F(GraphicsComposerHidlTest, SetColorMode) { |
301 | std::vector<ColorMode> modes = | 295 | std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay); |
302 | mComposerClient->getColorModes(mPrimaryDisplay); | 296 | for (auto mode : modes) { |
303 | for (auto mode : modes) { | 297 | mComposerClient->setColorMode(mPrimaryDisplay, mode); |
304 | mComposerClient->setColorMode(mPrimaryDisplay, mode); | 298 | } |
305 | } | ||
306 | } | 299 | } |
307 | 300 | ||
308 | /** | 301 | /** |
@@ -311,20 +304,20 @@ TEST_F(GraphicsComposerHidlTest, SetColorMode) { | |||
311 | * Test that IComposerClient::setPowerMode succeeds for all power modes. | 304 | * Test that IComposerClient::setPowerMode succeeds for all power modes. |
312 | */ | 305 | */ |
313 | TEST_F(GraphicsComposerHidlTest, SetPowerMode) { | 306 | TEST_F(GraphicsComposerHidlTest, SetPowerMode) { |
314 | std::vector<IComposerClient::PowerMode> modes; | 307 | std::vector<IComposerClient::PowerMode> modes; |
315 | modes.push_back(IComposerClient::PowerMode::OFF); | 308 | modes.push_back(IComposerClient::PowerMode::OFF); |
316 | 309 | ||
317 | if (mComposerClient->getDozeSupport(mPrimaryDisplay)) { | 310 | if (mComposerClient->getDozeSupport(mPrimaryDisplay)) { |
318 | modes.push_back(IComposerClient::PowerMode::DOZE); | 311 | modes.push_back(IComposerClient::PowerMode::DOZE); |
319 | modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND); | 312 | modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND); |
320 | } | 313 | } |
321 | 314 | ||
322 | // push ON last | 315 | // push ON last |
323 | modes.push_back(IComposerClient::PowerMode::ON); | 316 | modes.push_back(IComposerClient::PowerMode::ON); |
324 | 317 | ||
325 | for (auto mode : modes) { | 318 | for (auto mode : modes) { |
326 | mComposerClient->setPowerMode(mPrimaryDisplay, mode); | 319 | mComposerClient->setPowerMode(mPrimaryDisplay, mode); |
327 | } | 320 | } |
328 | } | 321 | } |
329 | 322 | ||
330 | /** | 323 | /** |
@@ -334,369 +327,365 @@ TEST_F(GraphicsComposerHidlTest, SetPowerMode) { | |||
334 | * spurious vsync events. | 327 | * spurious vsync events. |
335 | */ | 328 | */ |
336 | TEST_F(GraphicsComposerHidlTest, SetVsyncEnabled) { | 329 | TEST_F(GraphicsComposerHidlTest, SetVsyncEnabled) { |
337 | mComposerCallback->setVsyncAllowed(true); | 330 | mComposerCallback->setVsyncAllowed(true); |
338 | 331 | ||
339 | mComposerClient->setVsyncEnabled(mPrimaryDisplay, true); | 332 | mComposerClient->setVsyncEnabled(mPrimaryDisplay, true); |
340 | usleep(60 * 1000); | 333 | usleep(60 * 1000); |
341 | mComposerClient->setVsyncEnabled(mPrimaryDisplay, false); | 334 | mComposerClient->setVsyncEnabled(mPrimaryDisplay, false); |
342 | 335 | ||
343 | mComposerCallback->setVsyncAllowed(false); | 336 | mComposerCallback->setVsyncAllowed(false); |
344 | } | 337 | } |
345 | 338 | ||
346 | // Tests for IComposerClient::Command. | 339 | // Tests for IComposerClient::Command. |
347 | class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { | 340 | class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { |
348 | protected: | 341 | protected: |
349 | void SetUp() override { | 342 | void SetUp() override { |
350 | ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp()); | 343 | ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp()); |
351 | 344 | ||
352 | ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>()); | 345 | ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>()); |
353 | 346 | ||
354 | mWriter = std::make_unique<CommandWriterBase>(1024); | 347 | mWriter = std::make_unique<CommandWriterBase>(1024); |
355 | mReader = std::make_unique<TestCommandReader>(); | 348 | mReader = std::make_unique<TestCommandReader>(); |
356 | } | 349 | } |
357 | 350 | ||
358 | void TearDown() override { | 351 | void TearDown() override { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); } |
359 | ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); | ||
360 | } | ||
361 | 352 | ||
362 | const native_handle_t* allocate() { | 353 | const native_handle_t* allocate() { |
363 | IMapper::BufferDescriptorInfo info{}; | 354 | IMapper::BufferDescriptorInfo info{}; |
364 | info.width = 64; | 355 | info.width = 64; |
365 | info.height = 64; | 356 | info.height = 64; |
366 | info.layerCount = 1; | 357 | info.layerCount = 1; |
367 | info.format = PixelFormat::RGBA_8888; | 358 | info.format = PixelFormat::RGBA_8888; |
368 | info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | | 359 | info.usage = |
369 | BufferUsage::CPU_READ_OFTEN); | 360 | static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN); |
370 | 361 | ||
371 | return mGralloc->allocate(info); | 362 | return mGralloc->allocate(info); |
372 | } | 363 | } |
373 | 364 | ||
374 | void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); } | 365 | void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); } |
375 | 366 | ||
376 | std::unique_ptr<CommandWriterBase> mWriter; | 367 | std::unique_ptr<CommandWriterBase> mWriter; |
377 | std::unique_ptr<TestCommandReader> mReader; | 368 | std::unique_ptr<TestCommandReader> mReader; |
378 | 369 | ||
379 | private: | 370 | private: |
380 | std::unique_ptr<Gralloc> mGralloc; | 371 | std::unique_ptr<Gralloc> mGralloc; |
381 | }; | 372 | }; |
382 | 373 | ||
383 | /** | 374 | /** |
384 | * Test IComposerClient::Command::SET_COLOR_TRANSFORM. | 375 | * Test IComposerClient::Command::SET_COLOR_TRANSFORM. |
385 | */ | 376 | */ |
386 | TEST_F(GraphicsComposerHidlCommandTest, SET_COLOR_TRANSFORM) { | 377 | TEST_F(GraphicsComposerHidlCommandTest, SET_COLOR_TRANSFORM) { |
387 | const std::array<float, 16> identity = {{ | 378 | const std::array<float, 16> identity = {{ |
388 | 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, | 379 | 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, |
389 | 0.0f, 0.0f, 0.0f, 1.0f, | 380 | 1.0f, |
390 | }}; | 381 | }}; |
391 | 382 | ||
392 | mWriter->selectDisplay(mPrimaryDisplay); | 383 | mWriter->selectDisplay(mPrimaryDisplay); |
393 | mWriter->setColorTransform(identity.data(), ColorTransform::IDENTITY); | 384 | mWriter->setColorTransform(identity.data(), ColorTransform::IDENTITY); |
394 | 385 | ||
395 | execute(); | 386 | execute(); |
396 | } | 387 | } |
397 | 388 | ||
398 | /** | 389 | /** |
399 | * Test IComposerClient::Command::SET_CLIENT_TARGET. | 390 | * Test IComposerClient::Command::SET_CLIENT_TARGET. |
400 | */ | 391 | */ |
401 | TEST_F(GraphicsComposerHidlCommandTest, SET_CLIENT_TARGET) { | 392 | TEST_F(GraphicsComposerHidlCommandTest, SET_CLIENT_TARGET) { |
402 | mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount); | 393 | mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount); |
403 | 394 | ||
404 | mWriter->selectDisplay(mPrimaryDisplay); | 395 | mWriter->selectDisplay(mPrimaryDisplay); |
405 | mWriter->setClientTarget(0, nullptr, -1, Dataspace::UNKNOWN, | 396 | mWriter->setClientTarget(0, nullptr, -1, Dataspace::UNKNOWN, |
406 | std::vector<IComposerClient::Rect>()); | 397 | std::vector<IComposerClient::Rect>()); |
407 | 398 | ||
408 | execute(); | 399 | execute(); |
409 | } | 400 | } |
410 | 401 | ||
411 | /** | 402 | /** |
412 | * Test IComposerClient::Command::SET_OUTPUT_BUFFER. | 403 | * Test IComposerClient::Command::SET_OUTPUT_BUFFER. |
413 | */ | 404 | */ |
414 | TEST_F(GraphicsComposerHidlCommandTest, SET_OUTPUT_BUFFER) { | 405 | TEST_F(GraphicsComposerHidlCommandTest, SET_OUTPUT_BUFFER) { |
415 | if (mComposerClient->getMaxVirtualDisplayCount() == 0) { | 406 | if (mComposerClient->getMaxVirtualDisplayCount() == 0) { |
416 | GTEST_SUCCEED() << "no virtual display support"; | 407 | GTEST_SUCCEED() << "no virtual display support"; |
417 | return; | 408 | return; |
418 | } | 409 | } |
419 | 410 | ||
420 | Display display; | 411 | Display display; |
421 | PixelFormat format; | 412 | PixelFormat format; |
422 | ASSERT_NO_FATAL_FAILURE(display = mComposerClient->createVirtualDisplay( | 413 | ASSERT_NO_FATAL_FAILURE( |
423 | 64, 64, PixelFormat::IMPLEMENTATION_DEFINED, | 414 | display = mComposerClient->createVirtualDisplay(64, 64, PixelFormat::IMPLEMENTATION_DEFINED, |
424 | kBufferSlotCount, &format)); | 415 | kBufferSlotCount, &format)); |
425 | 416 | ||
426 | const native_handle_t* handle; | 417 | const native_handle_t* handle; |
427 | ASSERT_NO_FATAL_FAILURE(handle = allocate()); | 418 | ASSERT_NO_FATAL_FAILURE(handle = allocate()); |
428 | 419 | ||
429 | mWriter->selectDisplay(display); | 420 | mWriter->selectDisplay(display); |
430 | mWriter->setOutputBuffer(0, handle, -1); | 421 | mWriter->setOutputBuffer(0, handle, -1); |
431 | execute(); | 422 | execute(); |
432 | } | 423 | } |
433 | 424 | ||
434 | /** | 425 | /** |
435 | * Test IComposerClient::Command::VALIDATE_DISPLAY. | 426 | * Test IComposerClient::Command::VALIDATE_DISPLAY. |
436 | */ | 427 | */ |
437 | TEST_F(GraphicsComposerHidlCommandTest, VALIDATE_DISPLAY) { | 428 | TEST_F(GraphicsComposerHidlCommandTest, VALIDATE_DISPLAY) { |
438 | mWriter->selectDisplay(mPrimaryDisplay); | 429 | mWriter->selectDisplay(mPrimaryDisplay); |
439 | mWriter->validateDisplay(); | 430 | mWriter->validateDisplay(); |
440 | execute(); | 431 | execute(); |
441 | } | 432 | } |
442 | 433 | ||
443 | /** | 434 | /** |
444 | * Test IComposerClient::Command::ACCEPT_DISPLAY_CHANGES. | 435 | * Test IComposerClient::Command::ACCEPT_DISPLAY_CHANGES. |
445 | */ | 436 | */ |
446 | TEST_F(GraphicsComposerHidlCommandTest, ACCEPT_DISPLAY_CHANGES) { | 437 | TEST_F(GraphicsComposerHidlCommandTest, ACCEPT_DISPLAY_CHANGES) { |
447 | mWriter->selectDisplay(mPrimaryDisplay); | 438 | mWriter->selectDisplay(mPrimaryDisplay); |
448 | mWriter->validateDisplay(); | 439 | mWriter->validateDisplay(); |
449 | mWriter->acceptDisplayChanges(); | 440 | mWriter->acceptDisplayChanges(); |
450 | execute(); | 441 | execute(); |
451 | } | 442 | } |
452 | 443 | ||
453 | /** | 444 | /** |
454 | * Test IComposerClient::Command::PRESENT_DISPLAY. | 445 | * Test IComposerClient::Command::PRESENT_DISPLAY. |
455 | */ | 446 | */ |
456 | TEST_F(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY) { | 447 | TEST_F(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY) { |
457 | mWriter->selectDisplay(mPrimaryDisplay); | 448 | mWriter->selectDisplay(mPrimaryDisplay); |
458 | mWriter->validateDisplay(); | 449 | mWriter->validateDisplay(); |
459 | mWriter->presentDisplay(); | 450 | mWriter->presentDisplay(); |
460 | execute(); | 451 | execute(); |
461 | } | 452 | } |
462 | 453 | ||
463 | /** | 454 | /** |
464 | * Test IComposerClient::Command::SET_LAYER_CURSOR_POSITION. | 455 | * Test IComposerClient::Command::SET_LAYER_CURSOR_POSITION. |
465 | */ | 456 | */ |
466 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_CURSOR_POSITION) { | 457 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_CURSOR_POSITION) { |
467 | Layer layer; | 458 | Layer layer; |
468 | ASSERT_NO_FATAL_FAILURE( | 459 | ASSERT_NO_FATAL_FAILURE(layer = |
469 | layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); | 460 | mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); |
470 | 461 | ||
471 | mWriter->selectDisplay(mPrimaryDisplay); | 462 | mWriter->selectDisplay(mPrimaryDisplay); |
472 | mWriter->selectLayer(layer); | 463 | mWriter->selectLayer(layer); |
473 | mWriter->setLayerCursorPosition(1, 1); | 464 | mWriter->setLayerCursorPosition(1, 1); |
474 | mWriter->setLayerCursorPosition(0, 0); | 465 | mWriter->setLayerCursorPosition(0, 0); |
475 | execute(); | 466 | execute(); |
476 | } | 467 | } |
477 | 468 | ||
478 | /** | 469 | /** |
479 | * Test IComposerClient::Command::SET_LAYER_BUFFER. | 470 | * Test IComposerClient::Command::SET_LAYER_BUFFER. |
480 | */ | 471 | */ |
481 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_BUFFER) { | 472 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_BUFFER) { |
482 | auto handle = allocate(); | 473 | auto handle = allocate(); |
483 | ASSERT_NE(nullptr, handle); | 474 | ASSERT_NE(nullptr, handle); |
484 | 475 | ||
485 | Layer layer; | 476 | Layer layer; |
486 | ASSERT_NO_FATAL_FAILURE( | 477 | ASSERT_NO_FATAL_FAILURE(layer = |
487 | layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); | 478 | mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); |
488 | 479 | ||
489 | mWriter->selectDisplay(mPrimaryDisplay); | 480 | mWriter->selectDisplay(mPrimaryDisplay); |
490 | mWriter->selectLayer(layer); | 481 | mWriter->selectLayer(layer); |
491 | mWriter->setLayerBuffer(0, handle, -1); | 482 | mWriter->setLayerBuffer(0, handle, -1); |
492 | execute(); | 483 | execute(); |
493 | } | 484 | } |
494 | 485 | ||
495 | /** | 486 | /** |
496 | * Test IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE. | 487 | * Test IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE. |
497 | */ | 488 | */ |
498 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SURFACE_DAMAGE) { | 489 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SURFACE_DAMAGE) { |
499 | Layer layer; | 490 | Layer layer; |
500 | ASSERT_NO_FATAL_FAILURE( | 491 | ASSERT_NO_FATAL_FAILURE(layer = |
501 | layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); | 492 | mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); |
502 | 493 | ||
503 | IComposerClient::Rect empty{0, 0, 0, 0}; | 494 | IComposerClient::Rect empty{0, 0, 0, 0}; |
504 | IComposerClient::Rect unit{0, 0, 1, 1}; | 495 | IComposerClient::Rect unit{0, 0, 1, 1}; |
505 | 496 | ||
506 | mWriter->selectDisplay(mPrimaryDisplay); | 497 | mWriter->selectDisplay(mPrimaryDisplay); |
507 | mWriter->selectLayer(layer); | 498 | mWriter->selectLayer(layer); |
508 | mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, empty)); | 499 | mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, empty)); |
509 | mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, unit)); | 500 | mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, unit)); |
510 | mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>()); | 501 | mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>()); |
511 | execute(); | 502 | execute(); |
512 | } | 503 | } |
513 | 504 | ||
514 | /** | 505 | /** |
515 | * Test IComposerClient::Command::SET_LAYER_BLEND_MODE. | 506 | * Test IComposerClient::Command::SET_LAYER_BLEND_MODE. |
516 | */ | 507 | */ |
517 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_BLEND_MODE) { | 508 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_BLEND_MODE) { |
518 | Layer layer; | 509 | Layer layer; |
519 | ASSERT_NO_FATAL_FAILURE( | 510 | ASSERT_NO_FATAL_FAILURE(layer = |
520 | layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); | 511 | mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); |
521 | 512 | ||
522 | mWriter->selectDisplay(mPrimaryDisplay); | 513 | mWriter->selectDisplay(mPrimaryDisplay); |
523 | mWriter->selectLayer(layer); | 514 | mWriter->selectLayer(layer); |
524 | mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE); | 515 | mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE); |
525 | mWriter->setLayerBlendMode(IComposerClient::BlendMode::PREMULTIPLIED); | 516 | mWriter->setLayerBlendMode(IComposerClient::BlendMode::PREMULTIPLIED); |
526 | mWriter->setLayerBlendMode(IComposerClient::BlendMode::COVERAGE); | 517 | mWriter->setLayerBlendMode(IComposerClient::BlendMode::COVERAGE); |
527 | execute(); | 518 | execute(); |
528 | } | 519 | } |
529 | 520 | ||
530 | /** | 521 | /** |
531 | * Test IComposerClient::Command::SET_LAYER_COLOR. | 522 | * Test IComposerClient::Command::SET_LAYER_COLOR. |
532 | */ | 523 | */ |
533 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_COLOR) { | 524 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_COLOR) { |
534 | Layer layer; | 525 | Layer layer; |
535 | ASSERT_NO_FATAL_FAILURE( | 526 | ASSERT_NO_FATAL_FAILURE(layer = |
536 | layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); | 527 | mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); |
537 | 528 | ||
538 | mWriter->selectDisplay(mPrimaryDisplay); | 529 | mWriter->selectDisplay(mPrimaryDisplay); |
539 | mWriter->selectLayer(layer); | 530 | mWriter->selectLayer(layer); |
540 | mWriter->setLayerColor(IComposerClient::Color{0xff, 0xff, 0xff, 0xff}); | 531 | mWriter->setLayerColor(IComposerClient::Color{0xff, 0xff, 0xff, 0xff}); |
541 | mWriter->setLayerColor(IComposerClient::Color{0, 0, 0, 0}); | 532 | mWriter->setLayerColor(IComposerClient::Color{0, 0, 0, 0}); |
542 | execute(); | 533 | execute(); |
543 | } | 534 | } |
544 | 535 | ||
545 | /** | 536 | /** |
546 | * Test IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE. | 537 | * Test IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE. |
547 | */ | 538 | */ |
548 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_COMPOSITION_TYPE) { | 539 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_COMPOSITION_TYPE) { |
549 | Layer layer; | 540 | Layer layer; |
550 | ASSERT_NO_FATAL_FAILURE( | 541 | ASSERT_NO_FATAL_FAILURE(layer = |
551 | layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); | 542 | mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); |
552 | 543 | ||
553 | mWriter->selectDisplay(mPrimaryDisplay); | 544 | mWriter->selectDisplay(mPrimaryDisplay); |
554 | mWriter->selectLayer(layer); | 545 | mWriter->selectLayer(layer); |
555 | mWriter->setLayerCompositionType(IComposerClient::Composition::CLIENT); | 546 | mWriter->setLayerCompositionType(IComposerClient::Composition::CLIENT); |
556 | mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE); | 547 | mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE); |
557 | mWriter->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR); | 548 | mWriter->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR); |
558 | mWriter->setLayerCompositionType(IComposerClient::Composition::CURSOR); | 549 | mWriter->setLayerCompositionType(IComposerClient::Composition::CURSOR); |
559 | execute(); | 550 | execute(); |
560 | } | 551 | } |
561 | 552 | ||
562 | /** | 553 | /** |
563 | * Test IComposerClient::Command::SET_LAYER_DATASPACE. | 554 | * Test IComposerClient::Command::SET_LAYER_DATASPACE. |
564 | */ | 555 | */ |
565 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_DATASPACE) { | 556 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_DATASPACE) { |
566 | Layer layer; | 557 | Layer layer; |
567 | ASSERT_NO_FATAL_FAILURE( | 558 | ASSERT_NO_FATAL_FAILURE(layer = |
568 | layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); | 559 | mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); |
569 | 560 | ||
570 | mWriter->selectDisplay(mPrimaryDisplay); | 561 | mWriter->selectDisplay(mPrimaryDisplay); |
571 | mWriter->selectLayer(layer); | 562 | mWriter->selectLayer(layer); |
572 | mWriter->setLayerDataspace(Dataspace::UNKNOWN); | 563 | mWriter->setLayerDataspace(Dataspace::UNKNOWN); |
573 | execute(); | 564 | execute(); |
574 | } | 565 | } |
575 | 566 | ||
576 | /** | 567 | /** |
577 | * Test IComposerClient::Command::SET_LAYER_DISPLAY_FRAME. | 568 | * Test IComposerClient::Command::SET_LAYER_DISPLAY_FRAME. |
578 | */ | 569 | */ |
579 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_DISPLAY_FRAME) { | 570 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_DISPLAY_FRAME) { |
580 | Layer layer; | 571 | Layer layer; |
581 | ASSERT_NO_FATAL_FAILURE( | 572 | ASSERT_NO_FATAL_FAILURE(layer = |
582 | layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); | 573 | mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); |
583 | 574 | ||
584 | mWriter->selectDisplay(mPrimaryDisplay); | 575 | mWriter->selectDisplay(mPrimaryDisplay); |
585 | mWriter->selectLayer(layer); | 576 | mWriter->selectLayer(layer); |
586 | mWriter->setLayerDisplayFrame(IComposerClient::Rect{0, 0, 1, 1}); | 577 | mWriter->setLayerDisplayFrame(IComposerClient::Rect{0, 0, 1, 1}); |
587 | execute(); | 578 | execute(); |
588 | } | 579 | } |
589 | 580 | ||
590 | /** | 581 | /** |
591 | * Test IComposerClient::Command::SET_LAYER_PLANE_ALPHA. | 582 | * Test IComposerClient::Command::SET_LAYER_PLANE_ALPHA. |
592 | */ | 583 | */ |
593 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_PLANE_ALPHA) { | 584 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_PLANE_ALPHA) { |
594 | Layer layer; | 585 | Layer layer; |
595 | ASSERT_NO_FATAL_FAILURE( | 586 | ASSERT_NO_FATAL_FAILURE(layer = |
596 | layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); | 587 | mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); |
597 | 588 | ||
598 | mWriter->selectDisplay(mPrimaryDisplay); | 589 | mWriter->selectDisplay(mPrimaryDisplay); |
599 | mWriter->selectLayer(layer); | 590 | mWriter->selectLayer(layer); |
600 | mWriter->setLayerPlaneAlpha(0.0f); | 591 | mWriter->setLayerPlaneAlpha(0.0f); |
601 | mWriter->setLayerPlaneAlpha(1.0f); | 592 | mWriter->setLayerPlaneAlpha(1.0f); |
602 | execute(); | 593 | execute(); |
603 | } | 594 | } |
604 | 595 | ||
605 | /** | 596 | /** |
606 | * Test IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM. | 597 | * Test IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM. |
607 | */ | 598 | */ |
608 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SIDEBAND_STREAM) { | 599 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SIDEBAND_STREAM) { |
609 | if (!mComposer->hasCapability(IComposer::Capability::SIDEBAND_STREAM)) { | 600 | if (!mComposer->hasCapability(IComposer::Capability::SIDEBAND_STREAM)) { |
610 | GTEST_SUCCEED() << "no sideband stream support"; | 601 | GTEST_SUCCEED() << "no sideband stream support"; |
611 | return; | 602 | return; |
612 | } | 603 | } |
613 | 604 | ||
614 | auto handle = allocate(); | 605 | auto handle = allocate(); |
615 | ASSERT_NE(nullptr, handle); | 606 | ASSERT_NE(nullptr, handle); |
616 | 607 | ||
617 | Layer layer; | 608 | Layer layer; |
618 | ASSERT_NO_FATAL_FAILURE( | 609 | ASSERT_NO_FATAL_FAILURE(layer = |
619 | layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); | 610 | mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); |
620 | 611 | ||
621 | mWriter->selectDisplay(mPrimaryDisplay); | 612 | mWriter->selectDisplay(mPrimaryDisplay); |
622 | mWriter->selectLayer(layer); | 613 | mWriter->selectLayer(layer); |
623 | mWriter->setLayerSidebandStream(handle); | 614 | mWriter->setLayerSidebandStream(handle); |
624 | execute(); | 615 | execute(); |
625 | } | 616 | } |
626 | 617 | ||
627 | /** | 618 | /** |
628 | * Test IComposerClient::Command::SET_LAYER_SOURCE_CROP. | 619 | * Test IComposerClient::Command::SET_LAYER_SOURCE_CROP. |
629 | */ | 620 | */ |
630 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SOURCE_CROP) { | 621 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SOURCE_CROP) { |
631 | Layer layer; | 622 | Layer layer; |
632 | ASSERT_NO_FATAL_FAILURE( | 623 | ASSERT_NO_FATAL_FAILURE(layer = |
633 | layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); | 624 | mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); |
634 | 625 | ||
635 | mWriter->selectDisplay(mPrimaryDisplay); | 626 | mWriter->selectDisplay(mPrimaryDisplay); |
636 | mWriter->selectLayer(layer); | 627 | mWriter->selectLayer(layer); |
637 | mWriter->setLayerSourceCrop(IComposerClient::FRect{0.0f, 0.0f, 1.0f, 1.0f}); | 628 | mWriter->setLayerSourceCrop(IComposerClient::FRect{0.0f, 0.0f, 1.0f, 1.0f}); |
638 | execute(); | 629 | execute(); |
639 | } | 630 | } |
640 | 631 | ||
641 | /** | 632 | /** |
642 | * Test IComposerClient::Command::SET_LAYER_TRANSFORM. | 633 | * Test IComposerClient::Command::SET_LAYER_TRANSFORM. |
643 | */ | 634 | */ |
644 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_TRANSFORM) { | 635 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_TRANSFORM) { |
645 | Layer layer; | 636 | Layer layer; |
646 | ASSERT_NO_FATAL_FAILURE( | 637 | ASSERT_NO_FATAL_FAILURE(layer = |
647 | layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); | 638 | mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); |
648 | 639 | ||
649 | mWriter->selectDisplay(mPrimaryDisplay); | 640 | mWriter->selectDisplay(mPrimaryDisplay); |
650 | mWriter->selectLayer(layer); | 641 | mWriter->selectLayer(layer); |
651 | mWriter->setLayerTransform(static_cast<Transform>(0)); | 642 | mWriter->setLayerTransform(static_cast<Transform>(0)); |
652 | mWriter->setLayerTransform(Transform::FLIP_H); | 643 | mWriter->setLayerTransform(Transform::FLIP_H); |
653 | mWriter->setLayerTransform(Transform::FLIP_V); | 644 | mWriter->setLayerTransform(Transform::FLIP_V); |
654 | mWriter->setLayerTransform(Transform::ROT_90); | 645 | mWriter->setLayerTransform(Transform::ROT_90); |
655 | mWriter->setLayerTransform(Transform::ROT_180); | 646 | mWriter->setLayerTransform(Transform::ROT_180); |
656 | mWriter->setLayerTransform(Transform::ROT_270); | 647 | mWriter->setLayerTransform(Transform::ROT_270); |
657 | mWriter->setLayerTransform( | 648 | mWriter->setLayerTransform(static_cast<Transform>(Transform::FLIP_H | Transform::ROT_90)); |
658 | static_cast<Transform>(Transform::FLIP_H | Transform::ROT_90)); | 649 | mWriter->setLayerTransform(static_cast<Transform>(Transform::FLIP_V | Transform::ROT_90)); |
659 | mWriter->setLayerTransform( | 650 | execute(); |
660 | static_cast<Transform>(Transform::FLIP_V | Transform::ROT_90)); | ||
661 | execute(); | ||
662 | } | 651 | } |
663 | 652 | ||
664 | /** | 653 | /** |
665 | * Test IComposerClient::Command::SET_LAYER_VISIBLE_REGION. | 654 | * Test IComposerClient::Command::SET_LAYER_VISIBLE_REGION. |
666 | */ | 655 | */ |
667 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_VISIBLE_REGION) { | 656 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_VISIBLE_REGION) { |
668 | Layer layer; | 657 | Layer layer; |
669 | ASSERT_NO_FATAL_FAILURE( | 658 | ASSERT_NO_FATAL_FAILURE(layer = |
670 | layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); | 659 | mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); |
671 | 660 | ||
672 | IComposerClient::Rect empty{0, 0, 0, 0}; | 661 | IComposerClient::Rect empty{0, 0, 0, 0}; |
673 | IComposerClient::Rect unit{0, 0, 1, 1}; | 662 | IComposerClient::Rect unit{0, 0, 1, 1}; |
674 | 663 | ||
675 | mWriter->selectDisplay(mPrimaryDisplay); | 664 | mWriter->selectDisplay(mPrimaryDisplay); |
676 | mWriter->selectLayer(layer); | 665 | mWriter->selectLayer(layer); |
677 | mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, empty)); | 666 | mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, empty)); |
678 | mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, unit)); | 667 | mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, unit)); |
679 | mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>()); | 668 | mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>()); |
680 | execute(); | 669 | execute(); |
681 | } | 670 | } |
682 | 671 | ||
683 | /** | 672 | /** |
684 | * Test IComposerClient::Command::SET_LAYER_Z_ORDER. | 673 | * Test IComposerClient::Command::SET_LAYER_Z_ORDER. |
685 | */ | 674 | */ |
686 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_Z_ORDER) { | 675 | TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_Z_ORDER) { |
687 | Layer layer; | 676 | Layer layer; |
688 | ASSERT_NO_FATAL_FAILURE( | 677 | ASSERT_NO_FATAL_FAILURE(layer = |
689 | layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); | 678 | mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount)); |
690 | 679 | ||
691 | mWriter->selectDisplay(mPrimaryDisplay); | 680 | mWriter->selectDisplay(mPrimaryDisplay); |
692 | mWriter->selectLayer(layer); | 681 | mWriter->selectLayer(layer); |
693 | mWriter->setLayerZOrder(10); | 682 | mWriter->setLayerZOrder(10); |
694 | mWriter->setLayerZOrder(0); | 683 | mWriter->setLayerZOrder(0); |
695 | execute(); | 684 | execute(); |
696 | } | 685 | } |
697 | 686 | ||
698 | } // namespace anonymous | 687 | } // namespace |
699 | } // namespace tests | 688 | } // namespace vts |
700 | } // namespace V2_1 | 689 | } // namespace V2_1 |
701 | } // namespace composer | 690 | } // namespace composer |
702 | } // namespace graphics | 691 | } // namespace graphics |
@@ -704,7 +693,7 @@ TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_Z_ORDER) { | |||
704 | } // namespace android | 693 | } // namespace android |
705 | 694 | ||
706 | int main(int argc, char** argv) { | 695 | int main(int argc, char** argv) { |
707 | using android::hardware::graphics::composer::V2_1::tests::GraphicsComposerHidlEnvironment; | 696 | using android::hardware::graphics::composer::V2_1::vts::GraphicsComposerHidlEnvironment; |
708 | ::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance()); | 697 | ::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance()); |
709 | ::testing::InitGoogleTest(&argc, argv); | 698 | ::testing::InitGoogleTest(&argc, argv); |
710 | GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv); | 699 | GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv); |
diff --git a/graphics/composer/2.2/default/Android.bp b/graphics/composer/2.2/default/Android.bp new file mode 100644 index 00000000..906479e6 --- /dev/null +++ b/graphics/composer/2.2/default/Android.bp | |||
@@ -0,0 +1,31 @@ | |||
1 | cc_binary { | ||
2 | name: "android.hardware.graphics.composer@2.2-service", | ||
3 | defaults: ["hidl_defaults"], | ||
4 | vendor: true, | ||
5 | relative_install_path: "hw", | ||
6 | srcs: ["service.cpp"], | ||
7 | init_rc: ["android.hardware.graphics.composer@2.2-service.rc"], | ||
8 | header_libs: [ | ||
9 | "android.hardware.graphics.composer@2.2-passthrough", | ||
10 | ], | ||
11 | shared_libs: [ | ||
12 | "android.hardware.graphics.composer@2.1", | ||
13 | "android.hardware.graphics.composer@2.2", | ||
14 | "android.hardware.graphics.mapper@2.0", | ||
15 | "libbase", | ||
16 | "libbinder", | ||
17 | "libcutils", | ||
18 | "libfmq", | ||
19 | "libhardware", | ||
20 | "libhidlbase", | ||
21 | "libhidltransport", | ||
22 | "libhwc2on1adapter", | ||
23 | "libhwc2onfbadapter", | ||
24 | "liblog", | ||
25 | "libsync", | ||
26 | "libutils", | ||
27 | ], | ||
28 | cflags: [ | ||
29 | "-DLOG_TAG=\"ComposerHal\"" | ||
30 | ], | ||
31 | } | ||
diff --git a/graphics/composer/2.2/default/OWNERS b/graphics/composer/2.2/default/OWNERS new file mode 100644 index 00000000..4714be2d --- /dev/null +++ b/graphics/composer/2.2/default/OWNERS | |||
@@ -0,0 +1,5 @@ | |||
1 | # Graphics team | ||
2 | courtneygo@google.com | ||
3 | jessehall@google.com | ||
4 | olv@google.com | ||
5 | stoza@google.com | ||
diff --git a/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc new file mode 100644 index 00000000..a41d902c --- /dev/null +++ b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc | |||
@@ -0,0 +1,6 @@ | |||
1 | service vendor.hwcomposer-2-2 /vendor/bin/hw/android.hardware.graphics.composer@2.2-service | ||
2 | class hal animation | ||
3 | user system | ||
4 | group graphics drmrpc | ||
5 | capabilities SYS_NICE | ||
6 | onrestart restart surfaceflinger | ||
diff --git a/graphics/composer/2.2/default/service.cpp b/graphics/composer/2.2/default/service.cpp new file mode 100644 index 00000000..8c5ef189 --- /dev/null +++ b/graphics/composer/2.2/default/service.cpp | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * Copyright 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include <sched.h> | ||
18 | |||
19 | #include <android/hardware/graphics/composer/2.2/IComposer.h> | ||
20 | #include <binder/ProcessState.h> | ||
21 | #include <composer-passthrough/2.2/HwcLoader.h> | ||
22 | #include <hidl/HidlTransportSupport.h> | ||
23 | |||
24 | using android::hardware::graphics::composer::V2_2::IComposer; | ||
25 | using android::hardware::graphics::composer::V2_2::passthrough::HwcLoader; | ||
26 | |||
27 | int main() { | ||
28 | // the conventional HAL might start binder services | ||
29 | android::ProcessState::initWithDriver("/dev/vndbinder"); | ||
30 | android::ProcessState::self()->setThreadPoolMaxThreadCount(4); | ||
31 | android::ProcessState::self()->startThreadPool(); | ||
32 | |||
33 | // same as SF main thread | ||
34 | struct sched_param param = {0}; | ||
35 | param.sched_priority = 2; | ||
36 | if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK, ¶m) != 0) { | ||
37 | ALOGE("Couldn't set SCHED_FIFO: %d", errno); | ||
38 | } | ||
39 | |||
40 | android::hardware::configureRpcThreadpool(4, true /* will join */); | ||
41 | |||
42 | android::sp<IComposer> composer = HwcLoader::load(); | ||
43 | if (composer == nullptr) { | ||
44 | return 1; | ||
45 | } | ||
46 | if (composer->registerAsService() != android::NO_ERROR) { | ||
47 | ALOGE("failed to register service"); | ||
48 | return 1; | ||
49 | } | ||
50 | |||
51 | android::hardware::joinRpcThreadpool(); | ||
52 | |||
53 | ALOGE("service is terminating"); | ||
54 | return 1; | ||
55 | } | ||
diff --git a/graphics/composer/2.2/utils/hal/Android.bp b/graphics/composer/2.2/utils/hal/Android.bp new file mode 100644 index 00000000..10dcae4d --- /dev/null +++ b/graphics/composer/2.2/utils/hal/Android.bp | |||
@@ -0,0 +1,35 @@ | |||
1 | // | ||
2 | // Copyright (C) 2018 The Android Open Source Project | ||
3 | // | ||
4 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | // you may not use this file except in compliance with the License. | ||
6 | // You may obtain a copy of the License at | ||
7 | // | ||
8 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | // | ||
10 | // Unless required by applicable law or agreed to in writing, software | ||
11 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | // See the License for the specific language governing permissions and | ||
14 | // limitations under the License. | ||
15 | |||
16 | cc_library_headers { | ||
17 | name: "android.hardware.graphics.composer@2.2-hal", | ||
18 | defaults: ["hidl_defaults"], | ||
19 | vendor_available: true, | ||
20 | shared_libs: [ | ||
21 | "android.hardware.graphics.composer@2.2", | ||
22 | ], | ||
23 | export_shared_lib_headers: [ | ||
24 | "android.hardware.graphics.composer@2.2", | ||
25 | ], | ||
26 | header_libs: [ | ||
27 | "android.hardware.graphics.composer@2.2-command-buffer", | ||
28 | "android.hardware.graphics.composer@2.1-hal", | ||
29 | ], | ||
30 | export_header_lib_headers: [ | ||
31 | "android.hardware.graphics.composer@2.2-command-buffer", | ||
32 | "android.hardware.graphics.composer@2.1-hal", | ||
33 | ], | ||
34 | export_include_dirs: ["include"], | ||
35 | } | ||
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/Composer.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/Composer.h new file mode 100644 index 00000000..58bbaa57 --- /dev/null +++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/Composer.h | |||
@@ -0,0 +1,74 @@ | |||
1 | /* | ||
2 | * Copyright 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #pragma once | ||
18 | |||
19 | #ifndef LOG_TAG | ||
20 | #warning "Composer.h included without LOG_TAG" | ||
21 | #endif | ||
22 | |||
23 | #include <android/hardware/graphics/composer/2.2/IComposer.h> | ||
24 | #include <composer-hal/2.1/Composer.h> | ||
25 | #include <composer-hal/2.2/ComposerClient.h> | ||
26 | |||
27 | namespace android { | ||
28 | namespace hardware { | ||
29 | namespace graphics { | ||
30 | namespace composer { | ||
31 | namespace V2_2 { | ||
32 | namespace hal { | ||
33 | |||
34 | namespace detail { | ||
35 | |||
36 | // ComposerImpl implements V2_*::IComposer on top of V2_*::ComposerHal | ||
37 | template <typename Interface, typename Hal> | ||
38 | class ComposerImpl : public V2_1::hal::detail::ComposerImpl<Interface, Hal> { | ||
39 | public: | ||
40 | static std::unique_ptr<ComposerImpl> create(std::unique_ptr<Hal> hal) { | ||
41 | return std::make_unique<ComposerImpl>(std::move(hal)); | ||
42 | } | ||
43 | |||
44 | ComposerImpl(std::unique_ptr<Hal> hal) : BaseType2_1(std::move(hal)) {} | ||
45 | |||
46 | protected: | ||
47 | V2_1::IComposerClient* createClient() override { | ||
48 | auto client = ComposerClient::create(mHal.get()); | ||
49 | if (!client) { | ||
50 | return nullptr; | ||
51 | } | ||
52 | |||
53 | auto clientDestroyed = [this]() { onClientDestroyed(); }; | ||
54 | client->setOnClientDestroyed(clientDestroyed); | ||
55 | |||
56 | return client.release(); | ||
57 | } | ||
58 | |||
59 | private: | ||
60 | using BaseType2_1 = V2_1::hal::detail::ComposerImpl<Interface, Hal>; | ||
61 | using BaseType2_1::mHal; | ||
62 | using BaseType2_1::onClientDestroyed; | ||
63 | }; | ||
64 | |||
65 | } // namespace detail | ||
66 | |||
67 | using Composer = detail::ComposerImpl<IComposer, ComposerHal>; | ||
68 | |||
69 | } // namespace hal | ||
70 | } // namespace V2_2 | ||
71 | } // namespace composer | ||
72 | } // namespace graphics | ||
73 | } // namespace hardware | ||
74 | } // namespace android | ||
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h new file mode 100644 index 00000000..d550f834 --- /dev/null +++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerClient.h | |||
@@ -0,0 +1,162 @@ | |||
1 | /* | ||
2 | * Copyright 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #pragma once | ||
18 | |||
19 | #ifndef LOG_TAG | ||
20 | #warning "ComposerClient.h included without LOG_TAG" | ||
21 | #endif | ||
22 | |||
23 | #include <android/hardware/graphics/composer/2.2/IComposerClient.h> | ||
24 | #include <composer-hal/2.1/ComposerClient.h> | ||
25 | #include <composer-hal/2.2/ComposerCommandEngine.h> | ||
26 | #include <composer-hal/2.2/ComposerHal.h> | ||
27 | #include <composer-hal/2.2/ComposerResources.h> | ||
28 | |||
29 | namespace android { | ||
30 | namespace hardware { | ||
31 | namespace graphics { | ||
32 | namespace composer { | ||
33 | namespace V2_2 { | ||
34 | namespace hal { | ||
35 | |||
36 | namespace detail { | ||
37 | |||
38 | // ComposerClientImpl implements V2_*::IComposerClient on top of V2_*::ComposerHal | ||
39 | template <typename Interface, typename Hal> | ||
40 | class ComposerClientImpl : public V2_1::hal::detail::ComposerClientImpl<Interface, Hal> { | ||
41 | public: | ||
42 | static std::unique_ptr<ComposerClientImpl> create(Hal* hal) { | ||
43 | auto client = std::make_unique<ComposerClientImpl>(hal); | ||
44 | return client->init() ? std::move(client) : nullptr; | ||
45 | } | ||
46 | |||
47 | ComposerClientImpl(Hal* hal) : BaseType2_1(hal) {} | ||
48 | |||
49 | // IComposerClient 2.2 interface | ||
50 | |||
51 | Return<void> getPerFrameMetadataKeys( | ||
52 | Display display, IComposerClient::getPerFrameMetadataKeys_cb hidl_cb) override { | ||
53 | std::vector<IComposerClient::PerFrameMetadataKey> keys; | ||
54 | Error error = mHal->getPerFrameMetadataKeys(display, &keys); | ||
55 | hidl_cb(error, keys); | ||
56 | return Void(); | ||
57 | } | ||
58 | |||
59 | Return<void> getReadbackBufferAttributes( | ||
60 | Display display, IComposerClient::getReadbackBufferAttributes_cb hidl_cb) override { | ||
61 | PixelFormat format = static_cast<PixelFormat>(0); | ||
62 | Dataspace dataspace = Dataspace::UNKNOWN; | ||
63 | Error error = mHal->getReadbackBufferAttributes(display, &format, &dataspace); | ||
64 | hidl_cb(error, format, dataspace); | ||
65 | return Void(); | ||
66 | } | ||
67 | |||
68 | Return<void> getReadbackBufferFence( | ||
69 | Display display, IComposerClient::getReadbackBufferFence_cb hidl_cb) override { | ||
70 | base::unique_fd fenceFd; | ||
71 | Error error = mHal->getReadbackBufferFence(display, &fenceFd); | ||
72 | if (error != Error::NONE) { | ||
73 | hidl_cb(error, nullptr); | ||
74 | return Void(); | ||
75 | } | ||
76 | |||
77 | NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0); | ||
78 | hidl_cb(error, getFenceHandle(fenceFd, fenceStorage)); | ||
79 | return Void(); | ||
80 | } | ||
81 | |||
82 | Return<Error> setReadbackBuffer(Display display, const hidl_handle& buffer, | ||
83 | const hidl_handle& releaseFence) override { | ||
84 | base::unique_fd fenceFd; | ||
85 | Error error = getFenceFd(releaseFence, &fenceFd); | ||
86 | if (error != Error::NONE) { | ||
87 | return error; | ||
88 | } | ||
89 | |||
90 | auto resources = static_cast<ComposerResources*>(mResources.get()); | ||
91 | const native_handle_t* readbackBuffer; | ||
92 | ComposerResources::ReplacedBufferHandle replacedReadbackBuffer; | ||
93 | error = resources->getDisplayReadbackBuffer(display, buffer.getNativeHandle(), | ||
94 | &readbackBuffer, &replacedReadbackBuffer); | ||
95 | if (error != Error::NONE) { | ||
96 | return error; | ||
97 | } | ||
98 | |||
99 | return mHal->setReadbackBuffer(display, readbackBuffer, std::move(fenceFd)); | ||
100 | } | ||
101 | |||
102 | Return<Error> setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) override { | ||
103 | return mHal->setPowerMode_2_2(display, mode); | ||
104 | } | ||
105 | |||
106 | protected: | ||
107 | std::unique_ptr<V2_1::hal::ComposerResources> createResources() override { | ||
108 | return ComposerResources::create(); | ||
109 | } | ||
110 | |||
111 | std::unique_ptr<V2_1::hal::ComposerCommandEngine> createCommandEngine() override { | ||
112 | return std::make_unique<ComposerCommandEngine>( | ||
113 | mHal, static_cast<ComposerResources*>(mResources.get())); | ||
114 | } | ||
115 | |||
116 | // convert fenceFd to or from hidl_handle | ||
117 | static Error getFenceFd(const hidl_handle& fenceHandle, base::unique_fd* outFenceFd) { | ||
118 | auto handle = fenceHandle.getNativeHandle(); | ||
119 | if (handle && handle->numFds > 1) { | ||
120 | ALOGE("invalid fence handle with %d fds", handle->numFds); | ||
121 | return Error::BAD_PARAMETER; | ||
122 | } | ||
123 | |||
124 | int fenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1; | ||
125 | if (fenceFd >= 0) { | ||
126 | fenceFd = dup(fenceFd); | ||
127 | if (fenceFd < 0) { | ||
128 | return Error::NO_RESOURCES; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | outFenceFd->reset(fenceFd); | ||
133 | |||
134 | return Error::NONE; | ||
135 | } | ||
136 | |||
137 | static hidl_handle getFenceHandle(const base::unique_fd& fenceFd, char* handleStorage) { | ||
138 | native_handle_t* handle = nullptr; | ||
139 | if (fenceFd >= 0) { | ||
140 | handle = native_handle_init(handleStorage, 1, 0); | ||
141 | handle->data[0] = fenceFd; | ||
142 | } | ||
143 | |||
144 | return hidl_handle(handle); | ||
145 | } | ||
146 | |||
147 | private: | ||
148 | using BaseType2_1 = V2_1::hal::detail::ComposerClientImpl<Interface, Hal>; | ||
149 | using BaseType2_1::mHal; | ||
150 | using BaseType2_1::mResources; | ||
151 | }; | ||
152 | |||
153 | } // namespace detail | ||
154 | |||
155 | using ComposerClient = detail::ComposerClientImpl<IComposerClient, ComposerHal>; | ||
156 | |||
157 | } // namespace hal | ||
158 | } // namespace V2_2 | ||
159 | } // namespace composer | ||
160 | } // namespace graphics | ||
161 | } // namespace hardware | ||
162 | } // namespace android | ||
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h new file mode 100644 index 00000000..adcac463 --- /dev/null +++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerCommandEngine.h | |||
@@ -0,0 +1,103 @@ | |||
1 | /* | ||
2 | * Copyright 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #pragma once | ||
18 | |||
19 | #ifndef LOG_TAG | ||
20 | #warning "ComposerCommandEngine.h included without LOG_TAG" | ||
21 | #endif | ||
22 | |||
23 | #include <composer-command-buffer/2.2/ComposerCommandBuffer.h> | ||
24 | #include <composer-hal/2.1/ComposerCommandEngine.h> | ||
25 | #include <composer-hal/2.2/ComposerHal.h> | ||
26 | #include <composer-hal/2.2/ComposerResources.h> | ||
27 | |||
28 | namespace android { | ||
29 | namespace hardware { | ||
30 | namespace graphics { | ||
31 | namespace composer { | ||
32 | namespace V2_2 { | ||
33 | namespace hal { | ||
34 | |||
35 | class ComposerCommandEngine : public V2_1::hal::ComposerCommandEngine { | ||
36 | public: | ||
37 | ComposerCommandEngine(ComposerHal* hal, ComposerResources* resources) | ||
38 | : BaseType2_1(hal, resources), mHal(hal) {} | ||
39 | |||
40 | protected: | ||
41 | bool executeCommand(V2_1::IComposerClient::Command command, uint16_t length) override { | ||
42 | switch (static_cast<IComposerClient::Command>(command)) { | ||
43 | case IComposerClient::Command::SET_PER_FRAME_METADATA: | ||
44 | return executeSetPerFrameMetadata(length); | ||
45 | case IComposerClient::Command::SET_LAYER_FLOAT_COLOR: | ||
46 | return executeSetLayerFloatColor(length); | ||
47 | default: | ||
48 | return BaseType2_1::executeCommand(command, length); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | bool executeSetPerFrameMetadata(uint16_t length) { | ||
53 | // (key, value) pairs | ||
54 | if (length % 2 != 0) { | ||
55 | return false; | ||
56 | } | ||
57 | |||
58 | std::vector<IComposerClient::PerFrameMetadata> metadata; | ||
59 | metadata.reserve(length / 2); | ||
60 | while (length > 0) { | ||
61 | metadata.emplace_back(IComposerClient::PerFrameMetadata{ | ||
62 | static_cast<IComposerClient::PerFrameMetadataKey>(readSigned()), readFloat()}); | ||
63 | length -= 2; | ||
64 | } | ||
65 | |||
66 | auto err = mHal->setPerFrameMetadata(mCurrentDisplay, metadata); | ||
67 | if (err != Error::NONE) { | ||
68 | mWriter.setError(getCommandLoc(), err); | ||
69 | } | ||
70 | |||
71 | return true; | ||
72 | } | ||
73 | |||
74 | bool executeSetLayerFloatColor(uint16_t length) { | ||
75 | if (length != CommandWriterBase::kSetLayerFloatColorLength) { | ||
76 | return false; | ||
77 | } | ||
78 | |||
79 | auto err = mHal->setLayerFloatColor(mCurrentDisplay, mCurrentLayer, readFloatColor()); | ||
80 | if (err != Error::NONE) { | ||
81 | mWriter.setError(getCommandLoc(), err); | ||
82 | } | ||
83 | |||
84 | return true; | ||
85 | } | ||
86 | |||
87 | IComposerClient::FloatColor readFloatColor() { | ||
88 | return IComposerClient::FloatColor{readFloat(), readFloat(), readFloat(), readFloat()}; | ||
89 | } | ||
90 | |||
91 | private: | ||
92 | using BaseType2_1 = V2_1::hal::ComposerCommandEngine; | ||
93 | using BaseType2_1::mWriter; | ||
94 | |||
95 | ComposerHal* mHal; | ||
96 | }; | ||
97 | |||
98 | } // namespace hal | ||
99 | } // namespace V2_2 | ||
100 | } // namespace composer | ||
101 | } // namespace graphics | ||
102 | } // namespace hardware | ||
103 | } // namespace android | ||
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h new file mode 100644 index 00000000..30b36439 --- /dev/null +++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerHal.h | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * Copyright 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #pragma once | ||
18 | |||
19 | #include <android-base/unique_fd.h> | ||
20 | #include <android/hardware/graphics/composer/2.2/IComposer.h> | ||
21 | #include <android/hardware/graphics/composer/2.2/IComposerClient.h> | ||
22 | #include <composer-hal/2.1/ComposerHal.h> | ||
23 | |||
24 | namespace android { | ||
25 | namespace hardware { | ||
26 | namespace graphics { | ||
27 | namespace composer { | ||
28 | namespace V2_2 { | ||
29 | namespace hal { | ||
30 | |||
31 | using common::V1_0::Dataspace; | ||
32 | using common::V1_0::PixelFormat; | ||
33 | using V2_1::Display; | ||
34 | using V2_1::Error; | ||
35 | using V2_1::Layer; | ||
36 | |||
37 | class ComposerHal : public V2_1::hal::ComposerHal { | ||
38 | public: | ||
39 | // superceded by setPowerMode_2_2 | ||
40 | Error setPowerMode(Display display, V2_1::IComposerClient::PowerMode mode) override { | ||
41 | return setPowerMode_2_2(display, static_cast<IComposerClient::PowerMode>(mode)); | ||
42 | } | ||
43 | |||
44 | virtual Error getPerFrameMetadataKeys( | ||
45 | Display display, std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) = 0; | ||
46 | virtual Error setPerFrameMetadata( | ||
47 | Display display, const std::vector<IComposerClient::PerFrameMetadata>& metadata) = 0; | ||
48 | |||
49 | virtual Error getReadbackBufferAttributes(Display display, PixelFormat* outFormat, | ||
50 | Dataspace* outDataspace) = 0; | ||
51 | virtual Error setReadbackBuffer(Display display, const native_handle_t* bufferHandle, | ||
52 | base::unique_fd fenceFd) = 0; | ||
53 | virtual Error getReadbackBufferFence(Display display, base::unique_fd* outFenceFd) = 0; | ||
54 | |||
55 | virtual Error setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) = 0; | ||
56 | |||
57 | virtual Error setLayerFloatColor(Display display, Layer layer, | ||
58 | IComposerClient::FloatColor color) = 0; | ||
59 | }; | ||
60 | |||
61 | } // namespace hal | ||
62 | } // namespace V2_2 | ||
63 | } // namespace composer | ||
64 | } // namespace graphics | ||
65 | } // namespace hardware | ||
66 | } // namespace android | ||
diff --git a/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerResources.h b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerResources.h new file mode 100644 index 00000000..85b66517 --- /dev/null +++ b/graphics/composer/2.2/utils/hal/include/composer-hal/2.2/ComposerResources.h | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * Copyright 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #pragma once | ||
18 | |||
19 | #ifndef LOG_TAG | ||
20 | #warning "ComposerResources.h included without LOG_TAG" | ||
21 | #endif | ||
22 | |||
23 | #include <composer-hal/2.1/ComposerResources.h> | ||
24 | |||
25 | namespace android { | ||
26 | namespace hardware { | ||
27 | namespace graphics { | ||
28 | namespace composer { | ||
29 | namespace V2_2 { | ||
30 | namespace hal { | ||
31 | |||
32 | using V2_1::hal::ComposerHandleCache; | ||
33 | using V2_1::hal::ComposerHandleImporter; | ||
34 | |||
35 | class ComposerDisplayResource : public V2_1::hal::ComposerDisplayResource { | ||
36 | public: | ||
37 | ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer, | ||
38 | uint32_t outputBufferCacheSize) | ||
39 | : V2_1::hal::ComposerDisplayResource(type, importer, outputBufferCacheSize), | ||
40 | mReadbackBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, 1) {} | ||
41 | |||
42 | Error getReadbackBuffer(const native_handle_t* inHandle, const native_handle_t** outHandle, | ||
43 | const native_handle** outReplacedHandle) { | ||
44 | const uint32_t slot = 0; | ||
45 | const bool fromCache = false; | ||
46 | return mReadbackBufferCache.getHandle(slot, fromCache, inHandle, outHandle, | ||
47 | outReplacedHandle); | ||
48 | } | ||
49 | |||
50 | protected: | ||
51 | ComposerHandleCache mReadbackBufferCache; | ||
52 | }; | ||
53 | |||
54 | class ComposerResources : public V2_1::hal::ComposerResources { | ||
55 | public: | ||
56 | static std::unique_ptr<ComposerResources> create() { | ||
57 | auto resources = std::make_unique<ComposerResources>(); | ||
58 | return resources->init() ? std::move(resources) : nullptr; | ||
59 | } | ||
60 | |||
61 | Error getDisplayReadbackBuffer(Display display, const native_handle_t* rawHandle, | ||
62 | const native_handle_t** outHandle, | ||
63 | ReplacedBufferHandle* outReplacedHandle) { | ||
64 | // import buffer | ||
65 | const native_handle_t* importedHandle; | ||
66 | Error error = mImporter.importBuffer(rawHandle, &importedHandle); | ||
67 | if (error != Error::NONE) { | ||
68 | return error; | ||
69 | } | ||
70 | |||
71 | std::lock_guard<std::mutex> lock(mDisplayResourcesMutex); | ||
72 | |||
73 | auto iter = mDisplayResources.find(display); | ||
74 | if (iter == mDisplayResources.end()) { | ||
75 | mImporter.freeBuffer(importedHandle); | ||
76 | return Error::BAD_DISPLAY; | ||
77 | } | ||
78 | ComposerDisplayResource& displayResource = | ||
79 | *static_cast<ComposerDisplayResource*>(iter->second.get()); | ||
80 | |||
81 | // update cache | ||
82 | const native_handle_t* replacedHandle; | ||
83 | error = displayResource.getReadbackBuffer(importedHandle, outHandle, &replacedHandle); | ||
84 | if (error != Error::NONE) { | ||
85 | mImporter.freeBuffer(importedHandle); | ||
86 | return error; | ||
87 | } | ||
88 | |||
89 | outReplacedHandle->reset(&mImporter, replacedHandle); | ||
90 | return Error::NONE; | ||
91 | } | ||
92 | |||
93 | protected: | ||
94 | std::unique_ptr<V2_1::hal::ComposerDisplayResource> createDisplayResource( | ||
95 | ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) override { | ||
96 | return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize); | ||
97 | } | ||
98 | }; | ||
99 | |||
100 | } // namespace hal | ||
101 | } // namespace V2_2 | ||
102 | } // namespace composer | ||
103 | } // namespace graphics | ||
104 | } // namespace hardware | ||
105 | } // namespace android | ||
diff --git a/graphics/composer/2.2/utils/passthrough/Android.bp b/graphics/composer/2.2/utils/passthrough/Android.bp new file mode 100644 index 00000000..318ce914 --- /dev/null +++ b/graphics/composer/2.2/utils/passthrough/Android.bp | |||
@@ -0,0 +1,14 @@ | |||
1 | cc_library_headers { | ||
2 | name: "android.hardware.graphics.composer@2.2-passthrough", | ||
3 | defaults: ["hidl_defaults"], | ||
4 | vendor: true, | ||
5 | header_libs: [ | ||
6 | "android.hardware.graphics.composer@2.1-passthrough", | ||
7 | "android.hardware.graphics.composer@2.2-hal", | ||
8 | ], | ||
9 | export_header_lib_headers: [ | ||
10 | "android.hardware.graphics.composer@2.1-passthrough", | ||
11 | "android.hardware.graphics.composer@2.2-hal", | ||
12 | ], | ||
13 | export_include_dirs: ["include"], | ||
14 | } | ||
diff --git a/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h new file mode 100644 index 00000000..b251351f --- /dev/null +++ b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcHal.h | |||
@@ -0,0 +1,208 @@ | |||
1 | /* | ||
2 | * Copyright 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #pragma once | ||
18 | |||
19 | #ifndef LOG_TAG | ||
20 | #warning "HwcHal.h included without LOG_TAG" | ||
21 | #endif | ||
22 | |||
23 | #include <type_traits> | ||
24 | |||
25 | #include <composer-hal/2.2/ComposerHal.h> | ||
26 | #include <composer-passthrough/2.1/HwcHal.h> | ||
27 | |||
28 | namespace android { | ||
29 | namespace hardware { | ||
30 | namespace graphics { | ||
31 | namespace composer { | ||
32 | namespace V2_2 { | ||
33 | namespace passthrough { | ||
34 | |||
35 | namespace detail { | ||
36 | |||
37 | using common::V1_0::Dataspace; | ||
38 | using common::V1_0::PixelFormat; | ||
39 | using V2_1::Display; | ||
40 | using V2_1::Error; | ||
41 | using V2_1::Layer; | ||
42 | |||
43 | // HwcHalImpl implements V2_*::hal::ComposerHal on top of hwcomposer2 | ||
44 | template <typename Hal> | ||
45 | class HwcHalImpl : public V2_1::passthrough::detail::HwcHalImpl<Hal> { | ||
46 | public: | ||
47 | // XXX when can we return Error::UNSUPPORTED? | ||
48 | |||
49 | Error getPerFrameMetadataKeys( | ||
50 | Display display, std::vector<IComposerClient::PerFrameMetadataKey>* outKeys) override { | ||
51 | if (!mDispatch.getPerFrameMetadataKeys) { | ||
52 | return Error::UNSUPPORTED; | ||
53 | } | ||
54 | |||
55 | uint32_t count = 0; | ||
56 | int32_t error = mDispatch.getPerFrameMetadataKeys(mDevice, display, &count, nullptr); | ||
57 | if (error != HWC2_ERROR_NONE) { | ||
58 | return static_cast<Error>(error); | ||
59 | } | ||
60 | |||
61 | std::vector<IComposerClient::PerFrameMetadataKey> keys(count); | ||
62 | error = mDispatch.getPerFrameMetadataKeys( | ||
63 | mDevice, display, &count, | ||
64 | reinterpret_cast<std::underlying_type<IComposerClient::PerFrameMetadataKey>::type*>( | ||
65 | keys.data())); | ||
66 | if (error != HWC2_ERROR_NONE) { | ||
67 | return static_cast<Error>(error); | ||
68 | } | ||
69 | |||
70 | keys.resize(count); | ||
71 | *outKeys = std::move(keys); | ||
72 | return Error::NONE; | ||
73 | } | ||
74 | |||
75 | Error setPerFrameMetadata( | ||
76 | Display display, const std::vector<IComposerClient::PerFrameMetadata>& metadata) override { | ||
77 | if (!mDispatch.setPerFrameMetadata) { | ||
78 | return Error::UNSUPPORTED; | ||
79 | } | ||
80 | |||
81 | std::vector<int32_t> keys; | ||
82 | std::vector<float> values; | ||
83 | keys.reserve(metadata.size()); | ||
84 | values.reserve(metadata.size()); | ||
85 | for (const auto& m : metadata) { | ||
86 | keys.push_back(static_cast<int32_t>(m.key)); | ||
87 | values.push_back(m.value); | ||
88 | } | ||
89 | |||
90 | int32_t error = mDispatch.setPerFrameMetadata(mDevice, display, metadata.size(), | ||
91 | keys.data(), values.data()); | ||
92 | return static_cast<Error>(error); | ||
93 | } | ||
94 | |||
95 | Error getReadbackBufferAttributes(Display display, PixelFormat* outFormat, | ||
96 | Dataspace* outDataspace) override { | ||
97 | if (!mDispatch.getReadbackBufferAttributes) { | ||
98 | return Error::UNSUPPORTED; | ||
99 | } | ||
100 | |||
101 | int32_t format = 0; | ||
102 | int32_t dataspace = 0; | ||
103 | int32_t error = | ||
104 | mDispatch.getReadbackBufferAttributes(mDevice, display, &format, &dataspace); | ||
105 | if (error == HWC2_ERROR_NONE) { | ||
106 | *outFormat = static_cast<PixelFormat>(format); | ||
107 | *outDataspace = static_cast<Dataspace>(dataspace); | ||
108 | } | ||
109 | return static_cast<Error>(error); | ||
110 | } | ||
111 | |||
112 | Error setReadbackBuffer(Display display, const native_handle_t* bufferHandle, | ||
113 | base::unique_fd fenceFd) override { | ||
114 | if (!mDispatch.setReadbackBuffer) { | ||
115 | return Error::UNSUPPORTED; | ||
116 | } | ||
117 | |||
118 | int32_t error = | ||
119 | mDispatch.setReadbackBuffer(mDevice, display, bufferHandle, fenceFd.release()); | ||
120 | return static_cast<Error>(error); | ||
121 | } | ||
122 | |||
123 | Error getReadbackBufferFence(Display display, base::unique_fd* outFenceFd) override { | ||
124 | if (!mDispatch.getReadbackBufferFence) { | ||
125 | return Error::UNSUPPORTED; | ||
126 | } | ||
127 | |||
128 | int32_t fenceFd = -1; | ||
129 | int32_t error = mDispatch.getReadbackBufferFence(mDevice, display, &fenceFd); | ||
130 | outFenceFd->reset(fenceFd); | ||
131 | return static_cast<Error>(error); | ||
132 | } | ||
133 | |||
134 | Error setPowerMode_2_2(Display display, IComposerClient::PowerMode mode) override { | ||
135 | if (mode == IComposerClient::PowerMode::ON_SUSPEND) { | ||
136 | return Error::UNSUPPORTED; | ||
137 | } | ||
138 | return setPowerMode(display, static_cast<V2_1::IComposerClient::PowerMode>(mode)); | ||
139 | } | ||
140 | |||
141 | Error setLayerFloatColor(Display display, Layer layer, | ||
142 | IComposerClient::FloatColor color) override { | ||
143 | if (!mDispatch.setLayerFloatColor) { | ||
144 | return Error::UNSUPPORTED; | ||
145 | } | ||
146 | |||
147 | int32_t error = mDispatch.setLayerFloatColor( | ||
148 | mDevice, display, layer, hwc_float_color{color.r, color.g, color.b, color.a}); | ||
149 | return static_cast<Error>(error); | ||
150 | } | ||
151 | |||
152 | protected: | ||
153 | template <typename T> | ||
154 | bool initOptionalDispatch(hwc2_function_descriptor_t desc, T* outPfn) { | ||
155 | auto pfn = mDevice->getFunction(mDevice, desc); | ||
156 | if (pfn) { | ||
157 | *outPfn = reinterpret_cast<T>(pfn); | ||
158 | return true; | ||
159 | } else { | ||
160 | return false; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | bool initDispatch() override { | ||
165 | if (!BaseType2_1::initDispatch()) { | ||
166 | return false; | ||
167 | } | ||
168 | |||
169 | initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_FLOAT_COLOR, &mDispatch.setLayerFloatColor); | ||
170 | |||
171 | initOptionalDispatch(HWC2_FUNCTION_SET_PER_FRAME_METADATA, &mDispatch.setPerFrameMetadata); | ||
172 | initOptionalDispatch(HWC2_FUNCTION_GET_PER_FRAME_METADATA_KEYS, | ||
173 | &mDispatch.getPerFrameMetadataKeys); | ||
174 | |||
175 | initOptionalDispatch(HWC2_FUNCTION_SET_READBACK_BUFFER, &mDispatch.setReadbackBuffer); | ||
176 | initOptionalDispatch(HWC2_FUNCTION_GET_READBACK_BUFFER_ATTRIBUTES, | ||
177 | &mDispatch.getReadbackBufferAttributes); | ||
178 | initOptionalDispatch(HWC2_FUNCTION_GET_READBACK_BUFFER_FENCE, | ||
179 | &mDispatch.getReadbackBufferFence); | ||
180 | |||
181 | return true; | ||
182 | } | ||
183 | |||
184 | struct { | ||
185 | HWC2_PFN_SET_LAYER_FLOAT_COLOR setLayerFloatColor; | ||
186 | HWC2_PFN_SET_PER_FRAME_METADATA setPerFrameMetadata; | ||
187 | HWC2_PFN_GET_PER_FRAME_METADATA_KEYS getPerFrameMetadataKeys; | ||
188 | HWC2_PFN_SET_READBACK_BUFFER setReadbackBuffer; | ||
189 | HWC2_PFN_GET_READBACK_BUFFER_ATTRIBUTES getReadbackBufferAttributes; | ||
190 | HWC2_PFN_GET_READBACK_BUFFER_FENCE getReadbackBufferFence; | ||
191 | } mDispatch = {}; | ||
192 | |||
193 | private: | ||
194 | using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>; | ||
195 | using BaseType2_1::mDevice; | ||
196 | using BaseType2_1::setPowerMode; | ||
197 | }; | ||
198 | |||
199 | } // namespace detail | ||
200 | |||
201 | using HwcHal = detail::HwcHalImpl<hal::ComposerHal>; | ||
202 | |||
203 | } // namespace passthrough | ||
204 | } // namespace V2_2 | ||
205 | } // namespace composer | ||
206 | } // namespace graphics | ||
207 | } // namespace hardware | ||
208 | } // namespace android | ||
diff --git a/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h new file mode 100644 index 00000000..cb4a238f --- /dev/null +++ b/graphics/composer/2.2/utils/passthrough/include/composer-passthrough/2.2/HwcLoader.h | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * Copyright 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #pragma once | ||
18 | |||
19 | #ifndef LOG_TAG | ||
20 | #warning "HwcLoader.h included without LOG_TAG" | ||
21 | #endif | ||
22 | |||
23 | #include <composer-hal/2.2/Composer.h> | ||
24 | #include <composer-hal/2.2/ComposerHal.h> | ||
25 | #include <composer-passthrough/2.1/HwcLoader.h> | ||
26 | #include <composer-passthrough/2.2/HwcHal.h> | ||
27 | |||
28 | namespace android { | ||
29 | namespace hardware { | ||
30 | namespace graphics { | ||
31 | namespace composer { | ||
32 | namespace V2_2 { | ||
33 | namespace passthrough { | ||
34 | |||
35 | class HwcLoader : public V2_1::passthrough::HwcLoader { | ||
36 | public: | ||
37 | static IComposer* load() { | ||
38 | const hw_module_t* module = loadModule(); | ||
39 | if (!module) { | ||
40 | return nullptr; | ||
41 | } | ||
42 | |||
43 | auto hal = createHalWithAdapter(module); | ||
44 | if (!hal) { | ||
45 | return nullptr; | ||
46 | } | ||
47 | |||
48 | return createComposer(std::move(hal)).release(); | ||
49 | } | ||
50 | |||
51 | // create a ComposerHal instance | ||
52 | static std::unique_ptr<hal::ComposerHal> createHal(const hw_module_t* module) { | ||
53 | auto hal = std::make_unique<HwcHal>(); | ||
54 | return hal->initWithModule(module) ? std::move(hal) : nullptr; | ||
55 | } | ||
56 | |||
57 | // create a ComposerHal instance, insert an adapter if necessary | ||
58 | static std::unique_ptr<hal::ComposerHal> createHalWithAdapter(const hw_module_t* module) { | ||
59 | bool adapted; | ||
60 | hwc2_device_t* device = openDeviceWithAdapter(module, &adapted); | ||
61 | if (!device) { | ||
62 | return nullptr; | ||
63 | } | ||
64 | auto hal = std::make_unique<HwcHal>(); | ||
65 | return hal->initWithDevice(std::move(device), !adapted) ? std::move(hal) : nullptr; | ||
66 | } | ||
67 | |||
68 | // create an IComposer instance | ||
69 | static std::unique_ptr<IComposer> createComposer(std::unique_ptr<hal::ComposerHal> hal) { | ||
70 | return hal::Composer::create(std::move(hal)); | ||
71 | } | ||
72 | }; | ||
73 | |||
74 | } // namespace passthrough | ||
75 | } // namespace V2_2 | ||
76 | } // namespace composer | ||
77 | } // namespace graphics | ||
78 | } // namespace hardware | ||
79 | } // namespace android | ||
diff --git a/graphics/composer/2.2/utils/vts/Android.bp b/graphics/composer/2.2/utils/vts/Android.bp new file mode 100644 index 00000000..641fdcb7 --- /dev/null +++ b/graphics/composer/2.2/utils/vts/Android.bp | |||
@@ -0,0 +1,39 @@ | |||
1 | // | ||
2 | // Copyright (C) 2018 The Android Open Source Project | ||
3 | // | ||
4 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | // you may not use this file except in compliance with the License. | ||
6 | // You may obtain a copy of the License at | ||
7 | // | ||
8 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | // | ||
10 | // Unless required by applicable law or agreed to in writing, software | ||
11 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | // See the License for the specific language governing permissions and | ||
14 | // limitations under the License. | ||
15 | // | ||
16 | |||
17 | cc_library_static { | ||
18 | name: "android.hardware.graphics.composer@2.2-vts", | ||
19 | defaults: ["hidl_defaults"], | ||
20 | srcs: [ | ||
21 | "ComposerVts.cpp", | ||
22 | ], | ||
23 | static_libs: [ | ||
24 | "VtsHalHidlTargetTestBase", | ||
25 | "android.hardware.graphics.composer@2.1", | ||
26 | "android.hardware.graphics.composer@2.1-vts", | ||
27 | "android.hardware.graphics.composer@2.2", | ||
28 | ], | ||
29 | header_libs: [ | ||
30 | "android.hardware.graphics.composer@2.1-command-buffer", | ||
31 | "android.hardware.graphics.composer@2.2-command-buffer", | ||
32 | ], | ||
33 | cflags: [ | ||
34 | "-O0", | ||
35 | "-g", | ||
36 | "-DLOG_TAG=\"ComposerVts\"", | ||
37 | ], | ||
38 | export_include_dirs: ["include"], | ||
39 | } | ||
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerTestUtils.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp index 00946cef..b536f671 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerTestUtils.cpp +++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp | |||
@@ -14,22 +14,22 @@ | |||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <VtsHalHidlTargetTestBase.h> | 17 | #include <composer-vts/2.2/ComposerVts.h> |
18 | #include <hidl/HidlTransportUtils.h> | ||
19 | 18 | ||
19 | #include <VtsHalHidlTargetTestBase.h> | ||
20 | #include <composer-command-buffer/2.2/ComposerCommandBuffer.h> | 20 | #include <composer-command-buffer/2.2/ComposerCommandBuffer.h> |
21 | #include "2.2/VtsHalGraphicsComposerTestUtils.h" | 21 | #include <hidl/HidlTransportUtils.h> |
22 | 22 | ||
23 | namespace android { | 23 | namespace android { |
24 | namespace hardware { | 24 | namespace hardware { |
25 | namespace graphics { | 25 | namespace graphics { |
26 | namespace composer { | 26 | namespace composer { |
27 | namespace V2_2 { | 27 | namespace V2_2 { |
28 | namespace tests { | 28 | namespace vts { |
29 | 29 | ||
30 | using android::hardware::graphics::composer::V2_2::IComposerClient; | ||
31 | using android::hardware::details::getDescriptor; | ||
32 | using android::hardware::details::canCastInterface; | 30 | using android::hardware::details::canCastInterface; |
31 | using android::hardware::details::getDescriptor; | ||
32 | using android::hardware::graphics::composer::V2_2::IComposerClient; | ||
33 | 33 | ||
34 | std::unique_ptr<ComposerClient_v2_2> Composer_v2_2::createClient_v2_2() { | 34 | std::unique_ptr<ComposerClient_v2_2> Composer_v2_2::createClient_v2_2() { |
35 | std::unique_ptr<ComposerClient_v2_2> client; | 35 | std::unique_ptr<ComposerClient_v2_2> client; |
@@ -56,7 +56,7 @@ std::vector<IComposerClient::PerFrameMetadataKey> ComposerClient_v2_2::getPerFra | |||
56 | return keys; | 56 | return keys; |
57 | } | 57 | } |
58 | 58 | ||
59 | void ComposerClient_v2_2::execute_v2_2(V2_1::tests::TestCommandReader* reader, | 59 | void ComposerClient_v2_2::execute_v2_2(V2_1::vts::TestCommandReader* reader, |
60 | V2_2::CommandWriterBase* writer) { | 60 | V2_2::CommandWriterBase* writer) { |
61 | bool queueChanged = false; | 61 | bool queueChanged = false; |
62 | uint32_t commandLength = 0; | 62 | uint32_t commandLength = 0; |
@@ -119,7 +119,7 @@ void ComposerClient_v2_2::getReadbackBufferFence(Display display, int32_t* outFe | |||
119 | *outFence = 0; | 119 | *outFence = 0; |
120 | } | 120 | } |
121 | 121 | ||
122 | } // namespace tests | 122 | } // namespace vts |
123 | } // namespace V2_2 | 123 | } // namespace V2_2 |
124 | } // namespace composer | 124 | } // namespace composer |
125 | } // namespace graphics | 125 | } // namespace graphics |
diff --git a/graphics/composer/2.2/vts/functional/include/2.2/VtsHalGraphicsComposerTestUtils.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h index c5756ed8..eced69f2 100644 --- a/graphics/composer/2.2/vts/functional/include/2.2/VtsHalGraphicsComposerTestUtils.h +++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h | |||
@@ -22,11 +22,11 @@ | |||
22 | #include <unordered_set> | 22 | #include <unordered_set> |
23 | #include <vector> | 23 | #include <vector> |
24 | 24 | ||
25 | #include <VtsHalGraphicsComposerTestUtils.h> | ||
26 | #include <VtsHalHidlTargetTestBase.h> | 25 | #include <VtsHalHidlTargetTestBase.h> |
27 | #include <android/hardware/graphics/composer/2.2/IComposer.h> | 26 | #include <android/hardware/graphics/composer/2.2/IComposer.h> |
28 | #include <android/hardware/graphics/composer/2.2/IComposerClient.h> | 27 | #include <android/hardware/graphics/composer/2.2/IComposerClient.h> |
29 | #include <composer-command-buffer/2.2/ComposerCommandBuffer.h> | 28 | #include <composer-command-buffer/2.2/ComposerCommandBuffer.h> |
29 | #include <composer-vts/2.1/ComposerVts.h> | ||
30 | #include <utils/StrongPointer.h> | 30 | #include <utils/StrongPointer.h> |
31 | 31 | ||
32 | namespace android { | 32 | namespace android { |
@@ -34,7 +34,7 @@ namespace hardware { | |||
34 | namespace graphics { | 34 | namespace graphics { |
35 | namespace composer { | 35 | namespace composer { |
36 | namespace V2_2 { | 36 | namespace V2_2 { |
37 | namespace tests { | 37 | namespace vts { |
38 | 38 | ||
39 | using android::hardware::graphics::common::V1_0::ColorMode; | 39 | using android::hardware::graphics::common::V1_0::ColorMode; |
40 | using android::hardware::graphics::common::V1_0::Dataspace; | 40 | using android::hardware::graphics::common::V1_0::Dataspace; |
@@ -47,22 +47,22 @@ class ComposerClient_v2_2; | |||
47 | 47 | ||
48 | // Only thing I need for Composer_v2_2 is to create a v2_2 ComposerClient | 48 | // Only thing I need for Composer_v2_2 is to create a v2_2 ComposerClient |
49 | // Everything else is the same | 49 | // Everything else is the same |
50 | class Composer_v2_2 : public V2_1::tests::Composer { | 50 | class Composer_v2_2 : public V2_1::vts::Composer { |
51 | public: | 51 | public: |
52 | Composer_v2_2() : V2_1::tests::Composer(){}; | 52 | Composer_v2_2() : V2_1::vts::Composer(){}; |
53 | explicit Composer_v2_2(const std::string& name) : V2_1::tests::Composer(name){}; | 53 | explicit Composer_v2_2(const std::string& name) : V2_1::vts::Composer(name){}; |
54 | 54 | ||
55 | std::unique_ptr<ComposerClient_v2_2> createClient_v2_2(); | 55 | std::unique_ptr<ComposerClient_v2_2> createClient_v2_2(); |
56 | }; | 56 | }; |
57 | 57 | ||
58 | // A wrapper to IComposerClient. | 58 | // A wrapper to IComposerClient. |
59 | class ComposerClient_v2_2 | 59 | class ComposerClient_v2_2 |
60 | : public android::hardware::graphics::composer::V2_1::tests::ComposerClient { | 60 | : public android::hardware::graphics::composer::V2_1::vts::ComposerClient { |
61 | public: | 61 | public: |
62 | ComposerClient_v2_2(const sp<IComposerClient>& client) | 62 | ComposerClient_v2_2(const sp<IComposerClient>& client) |
63 | : V2_1::tests::ComposerClient(client), mClient_v2_2(client){}; | 63 | : V2_1::vts::ComposerClient(client), mClient_v2_2(client){}; |
64 | 64 | ||
65 | void execute_v2_2(V2_1::tests::TestCommandReader* reader, V2_2::CommandWriterBase* writer); | 65 | void execute_v2_2(V2_1::vts::TestCommandReader* reader, V2_2::CommandWriterBase* writer); |
66 | 66 | ||
67 | std::vector<IComposerClient::PerFrameMetadataKey> getPerFrameMetadataKeys(Display display); | 67 | std::vector<IComposerClient::PerFrameMetadataKey> getPerFrameMetadataKeys(Display display); |
68 | 68 | ||
@@ -76,7 +76,7 @@ class ComposerClient_v2_2 | |||
76 | sp<V2_2::IComposerClient> mClient_v2_2; | 76 | sp<V2_2::IComposerClient> mClient_v2_2; |
77 | }; | 77 | }; |
78 | 78 | ||
79 | } // namespace tests | 79 | } // namespace vts |
80 | } // namespace V2_2 | 80 | } // namespace V2_2 |
81 | } // namespace composer | 81 | } // namespace composer |
82 | } // namespace graphics | 82 | } // namespace graphics |
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp index 78322a11..77479009 100644 --- a/graphics/composer/2.2/vts/functional/Android.bp +++ b/graphics/composer/2.2/vts/functional/Android.bp | |||
@@ -14,37 +14,6 @@ | |||
14 | // limitations under the License. | 14 | // limitations under the License. |
15 | // | 15 | // |
16 | 16 | ||
17 | cc_library_static { | ||
18 | name: "libVtsHalGraphicsComposerTestUtils@2.2", | ||
19 | defaults: ["hidl_defaults"], | ||
20 | srcs: [ | ||
21 | "VtsHalGraphicsComposerTestUtils.cpp", | ||
22 | ], | ||
23 | shared_libs: [ | ||
24 | "android.hardware.graphics.composer@2.1", | ||
25 | "android.hardware.graphics.composer@2.2", | ||
26 | "libfmq", | ||
27 | "libsync", | ||
28 | ], | ||
29 | static_libs: [ | ||
30 | "libVtsHalGraphicsComposerTestUtils", | ||
31 | "VtsHalHidlTargetTestBase", | ||
32 | ], | ||
33 | header_libs: [ | ||
34 | "android.hardware.graphics.composer@2.1-command-buffer", | ||
35 | "android.hardware.graphics.composer@2.2-command-buffer", | ||
36 | ], | ||
37 | cflags: [ | ||
38 | "-Wall", | ||
39 | "-Wextra", | ||
40 | "-Werror", | ||
41 | "-O0", | ||
42 | "-g", | ||
43 | "-DLOG_TAG=\"GraphicsComposerTestUtils@2.2\"", | ||
44 | ], | ||
45 | export_include_dirs: ["include"], | ||
46 | } | ||
47 | |||
48 | cc_test { | 17 | cc_test { |
49 | name: "VtsHalGraphicsComposerV2_2TargetTest", | 18 | name: "VtsHalGraphicsComposerV2_2TargetTest", |
50 | defaults: ["VtsHalTargetTestDefaults"], | 19 | defaults: ["VtsHalTargetTestDefaults"], |
@@ -58,14 +27,13 @@ cc_test { | |||
58 | ], | 27 | ], |
59 | static_libs: [ | 28 | static_libs: [ |
60 | "android.hardware.graphics.allocator@2.0", | 29 | "android.hardware.graphics.allocator@2.0", |
61 | "android.hardware.graphics.composer@2.2", | ||
62 | "android.hardware.graphics.composer@2.1", | 30 | "android.hardware.graphics.composer@2.1", |
31 | "android.hardware.graphics.composer@2.1-vts", | ||
32 | "android.hardware.graphics.composer@2.2", | ||
33 | "android.hardware.graphics.composer@2.2-vts", | ||
63 | "android.hardware.graphics.mapper@2.0", | 34 | "android.hardware.graphics.mapper@2.0", |
64 | "android.hardware.graphics.mapper@2.0-vts", | 35 | "android.hardware.graphics.mapper@2.0-vts", |
65 | "android.hardware.graphics.mapper@2.1", | 36 | "android.hardware.graphics.mapper@2.1", |
66 | "libVtsHalGraphicsComposerTestUtils", | ||
67 | "libVtsHalGraphicsComposerTestUtils@2.2", | ||
68 | "libnativehelper", | ||
69 | ], | 37 | ], |
70 | header_libs: [ | 38 | header_libs: [ |
71 | "android.hardware.graphics.composer@2.1-command-buffer", | 39 | "android.hardware.graphics.composer@2.1-command-buffer", |
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp index 6fbdd3c8..c4943296 100644 --- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp +++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp | |||
@@ -16,23 +16,20 @@ | |||
16 | 16 | ||
17 | #define LOG_TAG "graphics_composer_hidl_hal_test@2.2" | 17 | #define LOG_TAG "graphics_composer_hidl_hal_test@2.2" |
18 | 18 | ||
19 | #include <VtsHalHidlTargetTestBase.h> | ||
19 | #include <android-base/logging.h> | 20 | #include <android-base/logging.h> |
20 | #include <android/hardware/graphics/mapper/2.1/IMapper.h> | 21 | #include <android/hardware/graphics/mapper/2.1/IMapper.h> |
22 | #include <composer-vts/2.1/GraphicsComposerCallback.h> | ||
23 | #include <composer-vts/2.1/TestCommandReader.h> | ||
24 | #include <composer-vts/2.2/ComposerVts.h> | ||
21 | #include <mapper-vts/2.0/MapperVts.h> | 25 | #include <mapper-vts/2.0/MapperVts.h> |
22 | #include <sync/sync.h> | ||
23 | #include "2.2/VtsHalGraphicsComposerTestUtils.h" | ||
24 | #include "GraphicsComposerCallback.h" | ||
25 | #include "TestCommandReader.h" | ||
26 | #include "VtsHalGraphicsComposerTestUtils.h" | ||
27 | |||
28 | #include <VtsHalHidlTargetTestBase.h> | ||
29 | 26 | ||
30 | namespace android { | 27 | namespace android { |
31 | namespace hardware { | 28 | namespace hardware { |
32 | namespace graphics { | 29 | namespace graphics { |
33 | namespace composer { | 30 | namespace composer { |
34 | namespace V2_2 { | 31 | namespace V2_2 { |
35 | namespace tests { | 32 | namespace vts { |
36 | namespace { | 33 | namespace { |
37 | 34 | ||
38 | using android::hardware::graphics::common::V1_0::BufferUsage; | 35 | using android::hardware::graphics::common::V1_0::BufferUsage; |
@@ -71,7 +68,7 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { | |||
71 | GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>())); | 68 | GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>())); |
72 | ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient_v2_2()); | 69 | ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient_v2_2()); |
73 | 70 | ||
74 | mComposerCallback = new V2_1::tests::GraphicsComposerCallback; | 71 | mComposerCallback = new V2_1::vts::GraphicsComposerCallback; |
75 | mComposerClient->registerCallback(mComposerCallback); | 72 | mComposerClient->registerCallback(mComposerCallback); |
76 | 73 | ||
77 | // assume the first display is primary and is never removed | 74 | // assume the first display is primary and is never removed |
@@ -95,7 +92,7 @@ class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase { | |||
95 | 92 | ||
96 | std::unique_ptr<Composer_v2_2> mComposer; | 93 | std::unique_ptr<Composer_v2_2> mComposer; |
97 | std::unique_ptr<ComposerClient_v2_2> mComposerClient; | 94 | std::unique_ptr<ComposerClient_v2_2> mComposerClient; |
98 | sp<V2_1::tests::GraphicsComposerCallback> mComposerCallback; | 95 | sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback; |
99 | // the first display and is assumed never to be removed | 96 | // the first display and is assumed never to be removed |
100 | Display mPrimaryDisplay; | 97 | Display mPrimaryDisplay; |
101 | 98 | ||
@@ -122,7 +119,7 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { | |||
122 | ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>()); | 119 | ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>()); |
123 | 120 | ||
124 | mWriter = std::make_unique<V2_2::CommandWriterBase>(1024); | 121 | mWriter = std::make_unique<V2_2::CommandWriterBase>(1024); |
125 | mReader = std::make_unique<V2_1::tests::TestCommandReader>(); | 122 | mReader = std::make_unique<V2_1::vts::TestCommandReader>(); |
126 | } | 123 | } |
127 | 124 | ||
128 | void TearDown() override { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); } | 125 | void TearDown() override { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); } |
@@ -142,7 +139,7 @@ class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest { | |||
142 | void execute() { mComposerClient->execute_v2_2(mReader.get(), mWriter.get()); } | 139 | void execute() { mComposerClient->execute_v2_2(mReader.get(), mWriter.get()); } |
143 | 140 | ||
144 | std::unique_ptr<V2_2::CommandWriterBase> mWriter; | 141 | std::unique_ptr<V2_2::CommandWriterBase> mWriter; |
145 | std::unique_ptr<V2_1::tests::TestCommandReader> mReader; | 142 | std::unique_ptr<V2_1::vts::TestCommandReader> mReader; |
146 | 143 | ||
147 | private: | 144 | private: |
148 | std::unique_ptr<Gralloc> mGralloc; | 145 | std::unique_ptr<Gralloc> mGralloc; |
@@ -239,7 +236,7 @@ TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_FLOAT_COLOR) { | |||
239 | } | 236 | } |
240 | 237 | ||
241 | } // namespace | 238 | } // namespace |
242 | } // namespace tests | 239 | } // namespace vts |
243 | } // namespace V2_2 | 240 | } // namespace V2_2 |
244 | } // namespace composer | 241 | } // namespace composer |
245 | } // namespace graphics | 242 | } // namespace graphics |
@@ -247,7 +244,7 @@ TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_FLOAT_COLOR) { | |||
247 | } // namespace android | 244 | } // namespace android |
248 | 245 | ||
249 | int main(int argc, char** argv) { | 246 | int main(int argc, char** argv) { |
250 | using android::hardware::graphics::composer::V2_2::tests::GraphicsComposerHidlEnvironment; | 247 | using android::hardware::graphics::composer::V2_2::vts::GraphicsComposerHidlEnvironment; |
251 | ::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance()); | 248 | ::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance()); |
252 | ::testing::InitGoogleTest(&argc, argv); | 249 | ::testing::InitGoogleTest(&argc, argv); |
253 | GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv); | 250 | GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv); |
diff --git a/neuralnetworks/1.1/types.hal b/neuralnetworks/1.1/types.hal index 18863d3e..fae5dd0c 100644 --- a/neuralnetworks/1.1/types.hal +++ b/neuralnetworks/1.1/types.hal | |||
@@ -330,4 +330,12 @@ struct Model { | |||
330 | * equals OperandLifeTime::CONSTANT_REFERENCE. | 330 | * equals OperandLifeTime::CONSTANT_REFERENCE. |
331 | */ | 331 | */ |
332 | vec<memory> pools; | 332 | vec<memory> pools; |
333 | |||
334 | /** | ||
335 | * 'true' indicates TENSOR_FLOAT32 may be calculated with range and/or | ||
336 | * precision as low as that of the IEEE 754 16-bit floating-point format. | ||
337 | * 'false' indicates TENSOR_FLOAT32 must be calculated using at least the | ||
338 | * range and precision of the IEEE 754 32-bit floating-point format. | ||
339 | */ | ||
340 | bool relaxComputationFloat32toFloat16; | ||
333 | }; | 341 | }; |