• 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 "base/MessageChannel.h"
21 #include "base/FunctorThread.h"
22 #include "base/Thread.h"
23 
24 class RenderWindowChannel;
25 struct RenderWindowMessage;
26 
27 // Helper class used to manage the sub-window that displays the emulated GPU
28 // output. To use it, do the following:
29 //
30 //  1) Create a new instance, passing the size of the emulated accelerated
31 //     framebuffer in pixels you need.
32 //
33 //  2) Check isValid() after construction. If false, the library could not
34 //     initialize the class properly, and one should abort.
35 //
36 //  3) Optional: call setPostCallback() to specify a callback function which
37 //     will be called everytime a new frame is drawn.
38 //
39 //  4) Call setupSubWindow() to setup a new sub-window within the UI window.
40 //     One can call removeSubWindow() to remove it, and one can call
41 //     setupSubWindow() + removeSubWindow() any number of time (e.g. for
42 //     changing the position / rotation of the subwindow).
43 //
44 //  5) Optional: call setRotation() to only change the display rotation of
45 //     the sub-window content.
46 //
47 //  6) Call repaint() to force a repaint().
48 //
49 class RenderWindow {
50 public:
51     // Create new instance. |width| and |height| are the dimensions of the
52     // emulated accelerated framebuffer. |use_thread| can be true to force
53     // the use of a separate thread, which might be required on some platforms
54     // to avoid GL-realted corruption issues in the main window. Call
55     // isValid() after construction to verify that it worked properly.
56     //
57     // |use_sub_window| is true if the client will call setupSubWindow(),
58     // and false if it will call setPostCallback().
59     //
60     // Note that this call doesn't display anything, it just initializes
61     // the library, use setupSubWindow() to display something.
62     RenderWindow(int width, int height, bool use_thread, bool use_sub_window,
63             bool egl2egl);
64 
65     // Destructor. This will automatically call removeSubWindow() is needed.
66     ~RenderWindow();
67 
68     // Returns true if the RenderWindow instance is valid, which really
69     // means that the constructor succeeded.
isValid()70     bool isValid() const { return mValid; }
71 
72     // Return misc. GL strings to the caller. On success, return true and sets
73     // |*vendor| to the GL vendor string, |*renderer| to the GL renderer one,
74     // and |*version| to the GL version one. On failure, return false.
75     bool getHardwareStrings(const char** vendor,
76                             const char** renderer,
77                             const char** version);
78 
79     // Specify a function that will be called everytime a new frame is
80     // displayed. This is relatively slow but allows one to capture the
81     // output.
82     void setPostCallback(emugl::Renderer::OnPostCallback onPost,
83                          void* onPostContext,
84                          uint32_t displayId,
85                          bool useBgraReadback = false);
86 
87     bool asyncReadbackSupported();
88     emugl::Renderer::ReadPixelsCallback getReadPixelsCallback();
89     emugl::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 private:
148     bool processMessage(const RenderWindowMessage& msg);
useThread()149     bool useThread() const { return mThread != nullptr; }
150 
151     bool mValid = false;
152     bool mHasSubWindow = false;
153     android::base::Thread* mThread = nullptr;
154     RenderWindowChannel* mChannel = nullptr;
155 
156     // A worker thread to run repost() commands asynchronously.
157     enum class RepostCommand : char {
158         Repost, Sync
159     };
160     android::base::MessageChannel<RepostCommand, 10> mRepostCommands;
161     android::base::FunctorThread mRepostThread;
162 
163     bool mPaused = false;
164 };
165 
166 #endif  // ANDROID_EMUGL_LIBRENDER_RENDER_WINDOW_H
167