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 "aemu/base/containers/SmallVector.h"
20 #include "aemu/base/export.h"
21 #include "aemu/base/files/StdioStream.h"
22 #include "aemu/base/system/System.h"
23 #include "snapshot/common.h"
24 
25 #include <functional>
26 #include <vector>
27 
28 namespace android {
29 namespace snapshot {
30 
31 class ITextureSaver {
32     DISALLOW_COPY_AND_ASSIGN(ITextureSaver);
33 
34 protected:
35     ~ITextureSaver() = default;
36 
37 public:
38     ITextureSaver() = default;
39 
40     using Buffer = android::base::SmallVector<unsigned char>;
41     using saver_t = std::function<void(android::base::Stream*, Buffer*)>;
42 
43     // Save texture to a stream as well as update the index
44     virtual void saveTexture(uint32_t texId, const saver_t& saver) = 0;
45     virtual bool hasError() const = 0;
46     virtual uint64_t diskSize() const = 0;
47     virtual bool compressed() const = 0;
48     virtual bool getDuration(uint64_t* duration) = 0;
49 };
50 
51 class TextureSaver final : public ITextureSaver {
52     DISALLOW_COPY_AND_ASSIGN(TextureSaver);
53 
54 public:
55     AEMU_EXPORT TextureSaver(android::base::StdioStream&& stream);
56     AEMU_EXPORT ~TextureSaver();
57     AEMU_EXPORT void saveTexture(uint32_t texId, const saver_t& saver) override;
58     AEMU_EXPORT void done();
59 
hasError()60     AEMU_EXPORT bool hasError() const override { return mHasError; }
diskSize()61     AEMU_EXPORT uint64_t diskSize() const override { return mDiskSize; }
compressed()62     AEMU_EXPORT bool compressed() const override { return mIndex.version > 1; }
63 
64     // getDuration():
65     // Returns true if there was save with measurable time
66     // (and writes it to |duration| if |duration| is not null),
67     // otherwise returns false.
getDuration(uint64_t * duration)68     AEMU_EXPORT bool getDuration(uint64_t* duration) override {
69         if (mEndTime < mStartTime) {
70             return false;
71         }
72 
73         if (duration) {
74             *duration = mEndTime - mStartTime;
75         }
76         return true;
77     }
78 
79 private:
80     struct FileIndex {
81         struct Texture {
82             uint32_t texId;
83             int64_t filePos;
84         };
85 
86         int64_t startPosInFile;
87         int32_t version = 2;
88         std::vector<Texture> textures;
89     };
90 
91     void writeIndex();
92 
93     android::base::StdioStream mStream;
94     // A buffer for fetching data from GPU memory to RAM.
95     android::base::SmallFixedVector<unsigned char, 128> mBuffer;
96 
97     FileIndex mIndex;
98     uint64_t mDiskSize = 0;
99     bool mFinished = false;
100     bool mHasError = false;
101 
102     uint64_t mStartTime = 0;
103     uint64_t mEndTime = 0;
104 };
105 
106 }  // namespace snapshot
107 }  // namespace android
108