blob: 907e63590c5687530645ac91be3abc657b4b6312 [file] [log] [blame]
// 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"
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, 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<RepostCommand, 10> mRepostCommands;
android::base::FunctorThread mRepostThread;
bool mPaused = false;
};
} // namespace gfxstream
#endif // ANDROID_EMUGL_LIBRENDER_RENDER_WINDOW_H