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 <condition_variable>
20 #include <memory>
21 #include <mutex>
22 #include <queue>
23 #include <thread>
24 
25 #include <EGL/egl.h>
26 
27 #include "Thread.h"
28 
29 #include "WorkerThread.h"
30 
31 namespace samples {
32 
33 class Settings;
34 
35 class Renderer {
36     // Allows construction with std::unique_ptr from a static method, but disallows construction
37     // outside of the class since no one else can construct a ConstructorTag
38     struct ConstructorTag {
39     };
40 
41 public:
Renderer(ConstructorTag)42     explicit Renderer(ConstructorTag) {}
43 
44     static Renderer *getInstance();
45 
46     // Sets the active window to render into
47     // Takes ownership of window and will release its reference
48     void setWindow(ANativeWindow *window, int32_t width, int32_t height);
49 
50     void start();
51 
52     void stop();
53 
54     float getAverageFps();
55 
56     void requestDraw();
57 
58     void setWorkload(int load);
59 
60 private:
61     class ThreadState {
62     public:
63         ThreadState();
64 
65         ~ThreadState();
66 
67         void onSettingsChanged(const Settings *);
68 
69         void clearSurface();
70 
71         bool configHasAttribute(EGLint attribute, EGLint value);
72 
73         EGLBoolean makeCurrent(EGLSurface surface);
74 
75         EGLDisplay display = EGL_NO_DISPLAY;
76         EGLConfig config = static_cast<EGLConfig>(0);
77         EGLSurface surface = EGL_NO_SURFACE;
78         EGLContext context = EGL_NO_CONTEXT;
79 
80         bool isStarted = false;
81 
82         std::chrono::time_point<std::chrono::steady_clock> lastUpdate = std::chrono::steady_clock::now();
83         float x = 0.0f;
84         float velocity = 1.6f;
85 
86         std::chrono::nanoseconds refreshPeriod = std::chrono::nanoseconds{0};
87         int64_t swapIntervalNS = 0;
88         int32_t width = 0;
89         int32_t height = 0;
90     };
91 
92     void draw(ThreadState *threadState);
93     void calculateFps();
94 
95     WorkerThread<ThreadState> mWorkerThread = {"Renderer", Affinity::Odd};
96 
97     class HotPocketState {
98     public:
99         void onSettingsChanged(const Settings *);
100 
101         bool isEnabled = false;
102         bool isStarted = false;
103     };
104 
105     WorkerThread<HotPocketState> mHotPocketThread = {"HotPocket", Affinity::Even};
106 
107     void spin();
108 
109     float averageFps = -1.0f;
110 
111     int mWorkload = 0;
112 };
113 
114 } // namespace samples
115