// Copyright 2014-2015 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef ANDROID_EMUGL_LIBRENDER_RENDER_WINDOW_H #define ANDROID_EMUGL_LIBRENDER_RENDER_WINDOW_H #include "render-utils/render_api.h" #include "aemu/base/synchronization/MessageChannel.h" #include "aemu/base/threads/FunctorThread.h" #include "aemu/base/threads/Thread.h" #include "gfxstream/host/Features.h" namespace gfxstream { class RenderWindowChannel; struct RenderWindowMessage; // Helper class used to manage the sub-window that displays the emulated GPU // output. To use it, do the following: // // 1) Create a new instance, passing the size of the emulated accelerated // framebuffer in pixels you need. // // 2) Check isValid() after construction. If false, the library could not // initialize the class properly, and one should abort. // // 3) Optional: call setPostCallback() to specify a callback function which // will be called everytime a new frame is drawn. // // 4) Call setupSubWindow() to setup a new sub-window within the UI window. // One can call removeSubWindow() to remove it, and one can call // setupSubWindow() + removeSubWindow() any number of time (e.g. for // changing the position / rotation of the subwindow). // // 5) Optional: call setRotation() to only change the display rotation of // the sub-window content. // // 6) Call repaint() to force a repaint(). // class RenderWindow { public: // Create new instance. |width| and |height| are the dimensions of the // emulated accelerated framebuffer. |use_thread| can be true to force // the use of a separate thread, which might be required on some platforms // to avoid GL-realted corruption issues in the main window. Call // isValid() after construction to verify that it worked properly. // // |use_sub_window| is true if the client will call setupSubWindow(), // and false if it will call setPostCallback(). // // Note that this call doesn't display anything, it just initializes // the library, use setupSubWindow() to display something. RenderWindow(int width, int height, gfxstream::host::FeatureSet features, bool use_thread, bool use_sub_window, bool egl2egl); // Destructor. This will automatically call removeSubWindow() is needed. ~RenderWindow(); // Returns true if the RenderWindow instance is valid, which really // means that the constructor succeeded. bool isValid() const { return mValid; } // Return misc. GL strings to the caller. On success, return true and sets // |*vendor| to the GL vendor string, |*renderer| to the GL renderer one, // and |*version| to the GL version one. On failure, return false. bool getHardwareStrings(const char** vendor, const char** renderer, const char** version); // Specify a function that will be called everytime a new frame is // displayed. This is relatively slow but allows one to capture the // output. void setPostCallback(Renderer::OnPostCallback onPost, void* onPostContext, uint32_t displayId, bool useBgraReadback = false); bool asyncReadbackSupported(); Renderer::ReadPixelsCallback getReadPixelsCallback(); Renderer::FlushReadPixelPipeline getFlushReadPixelPipeline(); // Start displaying the emulated framebuffer using a sub-window of a // parent |window| id. |wx|, |wy|, |ww| and |wh| are the position // and dimension of the sub-window, relative to its parent. // |fbw| and |fbh| are the dimensions of the underlying guest framebuffer. // |dpr| is the device pixel ratio for the monitor, which is required for // higher-density displays (such as retina). // |rotation| is a clockwise-rotation for the content. Only multiples of // 90. are accepted. Returns true on success, false otherwise. // // If the subwindow already exists, this function will update // the dimensions of the subwindow, backing framebuffer, and rendering // pipeline to reflect the new values. // // One can call removeSubWindow() to remove the sub-window. bool setupSubWindow(FBNativeWindowType window, int wx, int wy, int ww, int wh, int fbw, int fbh, float dpr, float rotation, bool deleteExisting, bool hideWindow); // Remove the sub-window created by calling setupSubWindow(). // Note that this doesn't discard the content of the emulated framebuffer, // it just hides it from the main window. Returns true on success, false // otherwise. bool removeSubWindow(); // Change the display rotation on the fly. |zRot| is a clockwise rotation // angle in degrees. Only multiples of 90. are accepted. void setRotation(float zRot); // Change the display translation. |px|,|py| are numbers between 0 and 1, // with (0,0) indicating "align the bottom left of the framebuffer with the // bottom left of the subwindow", and (1,1) indicating "align the top right of // the framebuffer with the top right of the subwindow." void setTranslation(float px, float py); // Receive a screen mask and pass it to TextureDraw void setScreenMask(int width, int height, const unsigned char* rgbaData); // Force a repaint of the whole content into the sub-window. void repaint(); // Returns whether or not the guest posted a frame. For checking emulator // liveness. bool hasGuestPostedAFrame(); // Resets whether the guest has posted a frame. void resetGuestPostedAFrame(); void setPaused(bool paused); void addListener(Renderer::FrameBufferChangeEventListener* listener); void removeListener(Renderer::FrameBufferChangeEventListener* listener); void setVsyncHz(int vsyncHz); void setDisplayConfigs(int configId, int w, int h, int dpiX, int dpiY); void setDisplayActiveConfig(int configId); private: bool processMessage(const RenderWindowMessage& msg); bool useThread() const { return mThread != nullptr; } bool mValid = false; bool mHasSubWindow = false; android::base::Thread* mThread = nullptr; RenderWindowChannel* mChannel = nullptr; // A worker thread to run repost() commands asynchronously. enum class RepostCommand : char { Repost, Sync }; android::base::MessageChannel mRepostCommands; android::base::FunctorThread mRepostThread; bool mPaused = false; }; } // namespace gfxstream #endif // ANDROID_EMUGL_LIBRENDER_RENDER_WINDOW_H