• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014-2015 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 #ifndef ANDROID_EMUGL_LIBRENDER_RENDER_WINDOW_H
16 #define ANDROID_EMUGL_LIBRENDER_RENDER_WINDOW_H
17 
18 #include "render_api.h"
19 
20 #include "aemu/base/synchronization/MessageChannel.h"
21 #include "aemu/base/threads/FunctorThread.h"
22 #include "aemu/base/threads/Thread.h"
23 
24 namespace gfxstream {
25 
26 class RenderWindowChannel;
27 struct RenderWindowMessage;
28 
29 // Helper class used to manage the sub-window that displays the emulated GPU
30 // output. To use it, do the following:
31 //
32 //  1) Create a new instance, passing the size of the emulated accelerated
33 //     framebuffer in pixels you need.
34 //
35 //  2) Check isValid() after construction. If false, the library could not
36 //     initialize the class properly, and one should abort.
37 //
38 //  3) Optional: call setPostCallback() to specify a callback function which
39 //     will be called everytime a new frame is drawn.
40 //
41 //  4) Call setupSubWindow() to setup a new sub-window within the UI window.
42 //     One can call removeSubWindow() to remove it, and one can call
43 //     setupSubWindow() + removeSubWindow() any number of time (e.g. for
44 //     changing the position / rotation of the subwindow).
45 //
46 //  5) Optional: call setRotation() to only change the display rotation of
47 //     the sub-window content.
48 //
49 //  6) Call repaint() to force a repaint().
50 //
51 class RenderWindow {
52 public:
53     // Create new instance. |width| and |height| are the dimensions of the
54     // emulated accelerated framebuffer. |use_thread| can be true to force
55     // the use of a separate thread, which might be required on some platforms
56     // to avoid GL-realted corruption issues in the main window. Call
57     // isValid() after construction to verify that it worked properly.
58     //
59     // |use_sub_window| is true if the client will call setupSubWindow(),
60     // and false if it will call setPostCallback().
61     //
62     // Note that this call doesn't display anything, it just initializes
63     // the library, use setupSubWindow() to display something.
64     RenderWindow(int width, int height, bool use_thread, bool use_sub_window,
65             bool egl2egl);
66 
67     // Destructor. This will automatically call removeSubWindow() is needed.
68     ~RenderWindow();
69 
70     // Returns true if the RenderWindow instance is valid, which really
71     // means that the constructor succeeded.
isValid()72     bool isValid() const { return mValid; }
73 
74     // Return misc. GL strings to the caller. On success, return true and sets
75     // |*vendor| to the GL vendor string, |*renderer| to the GL renderer one,
76     // and |*version| to the GL version one. On failure, return false.
77     bool getHardwareStrings(const char** vendor,
78                             const char** renderer,
79                             const char** version);
80 
81     // Specify a function that will be called everytime a new frame is
82     // displayed. This is relatively slow but allows one to capture the
83     // output.
84     void setPostCallback(Renderer::OnPostCallback onPost, void* onPostContext, uint32_t displayId,
85                          bool useBgraReadback = false);
86 
87     bool asyncReadbackSupported();
88     Renderer::ReadPixelsCallback getReadPixelsCallback();
89     Renderer::FlushReadPixelPipeline getFlushReadPixelPipeline();
90 
91     // Start displaying the emulated framebuffer using a sub-window of a
92     // parent |window| id. |wx|, |wy|, |ww| and |wh| are the position
93     // and dimension of the sub-window, relative to its parent.
94     // |fbw| and |fbh| are the dimensions of the underlying guest framebuffer.
95     // |dpr| is the device pixel ratio for the monitor, which is required for
96     // higher-density displays (such as retina).
97     // |rotation| is a clockwise-rotation for the content. Only multiples of
98     // 90. are accepted. Returns true on success, false otherwise.
99     //
100     // If the subwindow already exists, this function will update
101     // the dimensions of the subwindow, backing framebuffer, and rendering
102     // pipeline to reflect the new values.
103     //
104     // One can call removeSubWindow() to remove the sub-window.
105     bool setupSubWindow(FBNativeWindowType window,
106                         int wx,
107                         int wy,
108                         int ww,
109                         int wh,
110                         int fbw,
111                         int fbh,
112                         float dpr,
113                         float rotation,
114                         bool deleteExisting,
115                         bool hideWindow);
116 
117     // Remove the sub-window created by calling setupSubWindow().
118     // Note that this doesn't discard the content of the emulated framebuffer,
119     // it just hides it from the main window. Returns true on success, false
120     // otherwise.
121     bool removeSubWindow();
122 
123     // Change the display rotation on the fly. |zRot| is a clockwise rotation
124     // angle in degrees. Only multiples of 90. are accepted.
125     void setRotation(float zRot);
126 
127     // Change the display translation. |px|,|py| are numbers between 0 and 1,
128     // with (0,0) indicating "align the bottom left of the framebuffer with the
129     // bottom left of the subwindow", and (1,1) indicating "align the top right of
130     // the framebuffer with the top right of the subwindow."
131     void setTranslation(float px, float py);
132 
133     // Receive a screen mask and pass it to TextureDraw
134     void setScreenMask(int width, int height, const unsigned char* rgbaData);
135 
136     // Force a repaint of the whole content into the sub-window.
137     void repaint();
138 
139     // Returns whether or not the guest posted a frame. For checking emulator
140     // liveness.
141     bool hasGuestPostedAFrame();
142     // Resets whether the guest has posted a frame.
143     void resetGuestPostedAFrame();
144 
145     void setPaused(bool paused);
146 
147     void addListener(Renderer::FrameBufferChangeEventListener* listener);
148     void removeListener(Renderer::FrameBufferChangeEventListener* listener);
149 
150     void setVsyncHz(int vsyncHz);
151     void setDisplayConfigs(int configId, int w, int h, int dpiX, int dpiY);
152     void setDisplayActiveConfig(int configId);
153 private:
154     bool processMessage(const RenderWindowMessage& msg);
useThread()155     bool useThread() const { return mThread != nullptr; }
156 
157     bool mValid = false;
158     bool mHasSubWindow = false;
159     android::base::Thread* mThread = nullptr;
160     RenderWindowChannel* mChannel = nullptr;
161 
162     // A worker thread to run repost() commands asynchronously.
163     enum class RepostCommand : char {
164         Repost, Sync
165     };
166     android::base::MessageChannel<RepostCommand, 10> mRepostCommands;
167     android::base::FunctorThread mRepostThread;
168 
169     bool mPaused = false;
170 };
171 
172 }  // namespace gfxstream
173 
174 #endif  // ANDROID_EMUGL_LIBRENDER_RENDER_WINDOW_H
175