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