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