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