• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 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 #include "VirtioGpuTimelines.h"
15 
16 #include <cinttypes>
17 #include <cstdio>
18 
19 #include "host-common/GfxstreamFatalError.h"
20 
21 using TaskId = VirtioGpuTimelines::TaskId;
22 using CtxId = VirtioGpuTimelines::CtxId;
23 using FenceId = VirtioGpuTimelines::FenceId;
24 using AutoLock = android::base::AutoLock;
25 using emugl::ABORT_REASON_OTHER;
26 using emugl::FatalError;
27 
VirtioGpuTimelines()28 VirtioGpuTimelines::VirtioGpuTimelines() : mNextId(0) {}
29 
enqueueTask(CtxId ctxId)30 TaskId VirtioGpuTimelines::enqueueTask(CtxId ctxId) {
31     AutoLock lock(mLock);
32 
33     TaskId id = mNextId++;
34     std::shared_ptr<Task> task(new Task(id, ctxId), [this](Task *task) {
35         mTaskIdToTask.erase(task->mId);
36         delete task;
37     });
38     mTaskIdToTask[id] = task;
39     mTimelineQueues[ctxId].emplace_back(std::move(task));
40     return id;
41 }
42 
enqueueFence(CtxId ctxId,FenceId,FenceCompletionCallback fenceCompletionCallback)43 void VirtioGpuTimelines::enqueueFence(
44     CtxId ctxId, FenceId, FenceCompletionCallback fenceCompletionCallback) {
45     AutoLock lock(mLock);
46 
47     auto fence = std::make_unique<Fence>(fenceCompletionCallback);
48     mTimelineQueues[ctxId].emplace_back(std::move(fence));
49     poll_locked(ctxId);
50 }
51 
notifyTaskCompletion(TaskId taskId)52 void VirtioGpuTimelines::notifyTaskCompletion(TaskId taskId) {
53     AutoLock lock(mLock);
54     auto iTask = mTaskIdToTask.find(taskId);
55     if (iTask == mTaskIdToTask.end()) {
56         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
57             << "Task(id = " << static_cast<uint64_t>(taskId) << ") can't be found";
58     }
59     std::shared_ptr<Task> task = iTask->second.lock();
60     if (task == nullptr) {
61         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
62             << "Task(id = " << static_cast<uint64_t>(taskId) << ") has been destroyed";
63     }
64     if (task->mId != taskId) {
65         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
66             << "Task id mismatch. Expected " << static_cast<uint64_t>(taskId) << " Actual "
67             << static_cast<uint64_t>(task->mId);
68     }
69     if (task->mHasCompleted) {
70         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
71             << "Task(id = " << static_cast<uint64_t>(taskId) << ") has been set to completed.";
72     }
73     task->mHasCompleted = true;
74     poll_locked(task->mCtxId);
75 }
76 
poll_locked(CtxId ctxId)77 void VirtioGpuTimelines::poll_locked(CtxId ctxId) {
78     auto iTimelineQueue = mTimelineQueues.find(ctxId);
79     if (iTimelineQueue == mTimelineQueues.end()) {
80         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
81             << "Context(id = " << ctxId << " doesn't exist";
82     }
83     std::list<TimelineItem> &timelineQueue = iTimelineQueue->second;
84     auto i = timelineQueue.begin();
85     for (; i != timelineQueue.end(); i++) {
86         // This visitor will signal the fence and return whether the timeline
87         // item is an incompleted task.
88         struct {
89             bool operator()(std::unique_ptr<Fence> &fence) {
90                 (*fence->mCompletionCallback)();
91                 return false;
92             }
93             bool operator()(std::shared_ptr<Task> &task) {
94                 return !task->mHasCompleted;
95             }
96         } visitor;
97         if (std::visit(visitor, *i)) {
98             break;
99         }
100     }
101     timelineQueue.erase(timelineQueue.begin(), i);
102 }
103