提交 fbc8b984 编写于 作者: S Simon Fels

Implement support for host side multi-window management

上级 c4e1e291
...@@ -6,6 +6,8 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) ...@@ -6,6 +6,8 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := AnboxAppManager LOCAL_PACKAGE_NAME := AnboxAppManager
LOCAL_CERTIFICATE := platform LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true LOCAL_PRIVILEGED_MODULE := true
# We kick out several core packages here which would
# otherwise put up the base UI we don't want.
LOCAL_OVERRIDES_PACKAGES := \ LOCAL_OVERRIDES_PACKAGES := \
Home \ Home \
Launcher2 \ Launcher2 \
......
...@@ -18,6 +18,11 @@ ...@@ -18,6 +18,11 @@
#include <hardware/hardware.h> #include <hardware/hardware.h>
#include <hardware/hwcomposer.h> #include <hardware/hwcomposer.h>
#include <map>
#include <vector>
#include <algorithm>
#include <string>
#define LOG_NDEBUG 0 #define LOG_NDEBUG 0
#include <cutils/log.h> #include <cutils/log.h>
...@@ -67,8 +72,8 @@ struct HwcContext { ...@@ -67,8 +72,8 @@ struct HwcContext {
}; };
static void dump_layer(hwc_layer_1_t const* l) { static void dump_layer(hwc_layer_1_t const* l) {
ALOGI("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}", ALOGI("\tname='%s', type=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}",
l->compositionType, l->flags, l->handle, l->transform, l->blending, l->name, l->compositionType, l->flags, l->handle, l->transform, l->blending,
l->sourceCrop.left, l->sourceCrop.left,
l->sourceCrop.top, l->sourceCrop.top,
l->sourceCrop.right, l->sourceCrop.right,
...@@ -185,11 +190,22 @@ static int hwc_set(hwc_composer_device_1_t* dev, size_t numDisplays, ...@@ -185,11 +190,22 @@ static int hwc_set(hwc_composer_device_1_t* dev, size_t numDisplays,
return -EINVAL; return -EINVAL;
} }
ALOGI("Posting buffer %p\n", cb->hostHandle); rcEnc->rcPostLayer(rcEnc,
rcEnc->rcFBPost(rcEnc, cb->hostHandle); layer->name,
cb->hostHandle,
layer->sourceCrop.left,
layer->sourceCrop.top,
layer->sourceCrop.right,
layer->sourceCrop.bottom,
layer->displayFrame.left,
layer->displayFrame.top,
layer->displayFrame.right,
layer->displayFrame.bottom);
hostCon->flush(); hostCon->flush();
} }
rcEnc->rcPostAllLayersDone(rcEnc);
check_sync_fds(numDisplays, displays); check_sync_fds(numDisplays, displays);
return 0; return 0;
...@@ -226,8 +242,64 @@ static int hwc_device_close(hw_device_t* dev) { ...@@ -226,8 +242,64 @@ static int hwc_device_close(hw_device_t* dev) {
return 0; return 0;
} }
static int hwc_get_display_configs(hwc_composer_device_1* dev, int disp,
uint32_t* configs, size_t* numConfigs) {
ALOGI("%s", __PRETTY_FUNCTION__);
if (disp != 0) {
return -EINVAL;
}
if (*numConfigs > 0) {
// Config[0] will be passed in to getDisplayAttributes as the disp
// parameter. The ARC display supports only 1 configuration.
configs[0] = 0;
*numConfigs = 1;
}
return 0;
}
static int hwc_get_display_attributes(hwc_composer_device_1* dev,
int disp, uint32_t config,
const uint32_t* attributes,
int32_t* values) {
ALOGI("%s", __PRETTY_FUNCTION__);
if (disp != 0 || config != 0) {
return -EINVAL;
}
DEFINE_AND_VALIDATE_HOST_CONNECTION();
while (*attributes != HWC_DISPLAY_NO_ATTRIBUTE) {
switch (*attributes) {
case HWC_DISPLAY_VSYNC_PERIOD:
*values = rcEnc->rcGetDisplayVsyncPeriod(rcEnc, disp);
break;
case HWC_DISPLAY_WIDTH:
*values = rcEnc->rcGetDisplayWidth(rcEnc, disp);
break;
case HWC_DISPLAY_HEIGHT:
*values = rcEnc->rcGetDisplayHeight(rcEnc, disp);
break;
case HWC_DISPLAY_DPI_X:
*values = 1000 * rcEnc->rcGetDisplayDpiX(rcEnc, disp);
break;
case HWC_DISPLAY_DPI_Y:
*values = 1000 * rcEnc->rcGetDisplayDpiY(rcEnc, disp);
break;
default:
ALOGE("Unknown attribute value 0x%02x", *attributes);
}
++attributes;
++values;
}
return 0;
}
static int hwc_device_open(const hw_module_t* module, const char* name, hw_device_t** device) { static int hwc_device_open(const hw_module_t* module, const char* name, hw_device_t** device) {
ALOGI("%s", __PRETTY_FUNCTION__); ALOGI("%s", __PRETTY_FUNCTION__);
if (strcmp(name, HWC_HARDWARE_COMPOSER) != 0) if (strcmp(name, HWC_HARDWARE_COMPOSER) != 0)
return -EINVAL; return -EINVAL;
...@@ -241,9 +313,9 @@ static int hwc_device_open(const hw_module_t* module, const char* name, hw_devic ...@@ -241,9 +313,9 @@ static int hwc_device_open(const hw_module_t* module, const char* name, hw_devic
dev->device.eventControl = hwc_event_control; dev->device.eventControl = hwc_event_control;
dev->device.blank = hwc_blank; dev->device.blank = hwc_blank;
dev->device.query = hwc_query; dev->device.query = hwc_query;
dev->device.getDisplayConfigs = hwc_get_display_configs;
dev->device.getDisplayAttributes = hwc_get_display_attributes;
dev->device.registerProcs = hwc_register_procs; dev->device.registerProcs = hwc_register_procs;
// FIXME: eventually implement to dump specific information
dev->device.dump = nullptr;
*device = &dev->device.common; *device = &dev->device.common;
......
...@@ -2,6 +2,7 @@ set(SOURCES ...@@ -2,6 +2,7 @@ set(SOURCES
ColorBuffer.cpp ColorBuffer.cpp
FbConfig.cpp FbConfig.cpp
FrameBuffer.cpp FrameBuffer.cpp
LayerManager.cpp
NativeSubWindow_delegate.cpp NativeSubWindow_delegate.cpp
ReadBuffer.cpp ReadBuffer.cpp
RenderContext.cpp RenderContext.cpp
...@@ -9,7 +10,7 @@ set(SOURCES ...@@ -9,7 +10,7 @@ set(SOURCES
RenderServer.cpp RenderServer.cpp
RenderThread.cpp RenderThread.cpp
RenderThreadInfo.cpp RenderThreadInfo.cpp
render_api.cpp RenderApi.cpp
RenderWindow.cpp RenderWindow.cpp
SocketStream.cpp SocketStream.cpp
TcpStream.cpp TcpStream.cpp
......
...@@ -154,9 +154,6 @@ static char* getGLES1ExtensionString(EGLDisplay p_dpy) ...@@ -154,9 +154,6 @@ static char* getGLES1ExtensionString(EGLDisplay p_dpy)
void FrameBuffer::finalize(){ void FrameBuffer::finalize(){
m_colorbuffers.clear(); m_colorbuffers.clear();
if (m_useSubWindow) {
removeSubWindow();
}
m_windows.clear(); m_windows.clear();
m_contexts.clear(); m_contexts.clear();
s_egl.eglMakeCurrent(m_eglDisplay, NULL, NULL, NULL); s_egl.eglMakeCurrent(m_eglDisplay, NULL, NULL, NULL);
...@@ -431,32 +428,19 @@ bool FrameBuffer::initialize(EGLNativeDisplayType nativeDisplay, int width, int ...@@ -431,32 +428,19 @@ bool FrameBuffer::initialize(EGLNativeDisplayType nativeDisplay, int width, int
} }
FrameBuffer::FrameBuffer(int p_width, int p_height, bool useSubWindow) : FrameBuffer::FrameBuffer(int p_width, int p_height, bool useSubWindow) :
m_framebufferWidth(p_width),
m_framebufferHeight(p_height),
m_windowWidth(p_width),
m_windowHeight(p_height),
m_useSubWindow(useSubWindow), m_useSubWindow(useSubWindow),
m_configs(NULL), m_configs(NULL),
m_eglDisplay(EGL_NO_DISPLAY), m_eglDisplay(EGL_NO_DISPLAY),
m_colorBufferHelper(new ColorBufferHelper(this)), m_colorBufferHelper(new ColorBufferHelper(this)),
m_eglSurface(EGL_NO_SURFACE),
m_eglContext(EGL_NO_CONTEXT), m_eglContext(EGL_NO_CONTEXT),
m_pbufContext(EGL_NO_CONTEXT), m_pbufContext(EGL_NO_CONTEXT),
m_prevContext(EGL_NO_CONTEXT), m_prevContext(EGL_NO_CONTEXT),
m_prevReadSurf(EGL_NO_SURFACE), m_prevReadSurf(EGL_NO_SURFACE),
m_prevDrawSurf(EGL_NO_SURFACE), m_prevDrawSurf(EGL_NO_SURFACE),
m_subWin((EGLNativeWindowType)0),
m_textureDraw(NULL), m_textureDraw(NULL),
m_lastPostedColorBuffer(0), m_lastPostedColorBuffer(0),
m_zRot(0.0f),
m_px(0),
m_py(0),
m_eglContextInitialized(false),
m_statsNumFrames(0), m_statsNumFrames(0),
m_statsStartTime(0LL), m_statsStartTime(0LL),
m_onPost(NULL),
m_onPostContext(NULL),
m_fbImage(NULL),
m_glVendor(NULL), m_glVendor(NULL),
m_glRenderer(NULL), m_glRenderer(NULL),
m_glVersion(NULL) m_glVersion(NULL)
...@@ -468,147 +452,68 @@ FrameBuffer::~FrameBuffer() { ...@@ -468,147 +452,68 @@ FrameBuffer::~FrameBuffer() {
delete m_textureDraw; delete m_textureDraw;
delete m_configs; delete m_configs;
delete m_colorBufferHelper; delete m_colorBufferHelper;
free(m_fbImage);
}
void FrameBuffer::setPostCallback(OnPostFn onPost, void* onPostContext)
{
emugl::Mutex::AutoLock mutex(m_lock);
m_onPost = onPost;
m_onPostContext = onPostContext;
if (m_onPost && !m_fbImage) {
m_fbImage = (unsigned char*)malloc(4 * m_framebufferWidth * m_framebufferHeight);
if (!m_fbImage) {
ERR("out of memory, cancelling OnPost callback");
m_onPost = NULL;
m_onPostContext = NULL;
return;
}
}
} }
static void subWindowRepaint(void* param) { struct FrameBufferWindow {
auto fb = static_cast<FrameBuffer*>(param); EGLNativeWindowType native_window = 0;
fb->repost(); EGLSurface surface = EGL_NO_SURFACE;
} };
bool FrameBuffer::setupSubWindow(FBNativeWindowType p_window,
int wx,
int wy,
int ww,
int wh,
int fbw,
int fbh,
float dpr,
float zRot) {
bool success = false;
if (!m_useSubWindow) {
ERR("%s: Cannot create native sub-window in this configuration\n",
__FUNCTION__);
return false;
}
FrameBufferWindow* FrameBuffer::createWindow(int x, int y, int width, int height) {
m_lock.lock(); m_lock.lock();
// If the subwindow doesn't exist, create it with the appropriate dimensions auto native_window = createSubWindow(0, x, y, width, height);
if (!m_subWin) { if (!native_window) {
m_lock.unlock();
// Create native subwindow for FB display output return nullptr;
m_x = wx;
m_y = wy;
m_windowWidth = ww;
m_windowHeight = wh;
m_subWin = createSubWindow(p_window, m_x, m_y,
m_windowWidth, m_windowHeight, subWindowRepaint, this);
if (m_subWin) {
m_nativeWindow = p_window;
// create EGLSurface from the generated subwindow
m_eglSurface = s_egl.eglCreateWindowSurface(m_eglDisplay,
m_eglConfig,
m_subWin,
NULL);
if (m_eglSurface == EGL_NO_SURFACE) {
// NOTE: This can typically happen with software-only renderers like OSMesa.
destroySubWindow(m_subWin);
m_subWin = (EGLNativeWindowType)0;
} else {
m_px = 0;
m_py = 0;
success = true;
}
}
} }
// At this point, if the subwindow doesn't exist, it is because it either couldn't be created auto window = new FrameBufferWindow;
// in the first place or the EGLSurface couldn't be created. window->native_window = native_window;
if (m_subWin && bindSubwin_locked()) {
// Only attempt to update window geometry if anything has actually changed. window->surface = s_egl.eglCreateWindowSurface(
if (!(m_x == wx && m_eglDisplay, m_eglConfig, window->native_window, nullptr);
m_y == wy && if (window->surface == EGL_NO_SURFACE) {
m_windowWidth == ww && destroyWindow(window);
m_windowHeight == wh)) { m_lock.unlock();
return nullptr;
}
m_x = wx; if (!bindWindow_locked(window)) {
m_y = wy; destroyWindow(window);
m_windowWidth = ww; m_lock.unlock();
m_windowHeight = wh; return nullptr;
}
success = ::moveSubWindow(m_nativeWindow, m_subWin, s_gles2.glViewport(0, 0, width, height);
m_x, m_y, m_windowWidth, m_windowHeight); s_gles2.glClear(GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT);
s_egl.eglSwapBuffers(m_eglDisplay, window->surface);
// Otherwise, ensure that at least viewport parameters are properly updated. unbind_locked();
} else {
success = true;
}
if (success) {
// Subwin creation or movement was successful,
// update viewport and z rotation and draw
// the last posted color buffer.
s_gles2.glViewport(0, 0, fbw * dpr, fbh * dpr);
m_dpr = dpr;
m_zRot = zRot;
if (m_lastPostedColorBuffer) {
post(m_lastPostedColorBuffer, false);
} else {
s_gles2.glClear(GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT);
s_egl.eglSwapBuffers(m_eglDisplay, m_eglSurface);
}
}
unbind_locked();
}
m_lock.unlock(); m_lock.unlock();
return success;
return window;
} }
bool FrameBuffer::removeSubWindow() { void FrameBuffer::destroyWindow(FrameBufferWindow *window) {
if (!m_useSubWindow) { if (!window)
ERR("%s: Cannot remove native sub-window in this configuration\n", return;
__FUNCTION__);
return false;
}
bool removed = false;
m_lock.lock(); m_lock.lock();
if (m_subWin) {
s_egl.eglMakeCurrent(m_eglDisplay, NULL, NULL, NULL);
s_egl.eglDestroySurface(m_eglDisplay, m_eglSurface);
destroySubWindow(m_subWin);
m_eglSurface = EGL_NO_SURFACE; s_egl.eglMakeCurrent(m_eglDisplay, nullptr, nullptr, nullptr);
m_subWin = (EGLNativeWindowType)0;
removed = true; if (window->surface != EGL_NO_SURFACE)
} s_egl.eglDestroySurface(m_eglDisplay, window->surface);
destroySubWindow(window->native_window);
delete window;
m_lock.unlock(); m_lock.unlock();
return removed;
} }
HandleType FrameBuffer::genHandle() HandleType FrameBuffer::genHandle()
...@@ -1021,25 +926,18 @@ bool FrameBuffer::bind_locked() ...@@ -1021,25 +926,18 @@ bool FrameBuffer::bind_locked()
return true; return true;
} }
bool FrameBuffer::bindSubwin_locked() bool FrameBuffer::bindWindow_locked(FrameBufferWindow *window)
{ {
EGLContext prevContext = s_egl.eglGetCurrentContext(); EGLContext prevContext = s_egl.eglGetCurrentContext();
EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ); EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ);
EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW); EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW);
if (!s_egl.eglMakeCurrent(m_eglDisplay, m_eglSurface, if (!s_egl.eglMakeCurrent(m_eglDisplay, window->surface,
m_eglSurface, m_eglContext)) { window->surface, m_eglContext)) {
ERR("eglMakeCurrent failed\n"); ERR("eglMakeCurrent failed\n");
return false; return false;
} }
//
// initialize GL state in eglContext if not yet initilaized
//
if (!m_eglContextInitialized) {
m_eglContextInitialized = true;
}
m_prevContext = prevContext; m_prevContext = prevContext;
m_prevReadSurf = prevReadSurf; m_prevReadSurf = prevReadSurf;
m_prevDrawSurf = prevDrawSurf; m_prevDrawSurf = prevDrawSurf;
...@@ -1059,64 +957,37 @@ bool FrameBuffer::unbind_locked() ...@@ -1059,64 +957,37 @@ bool FrameBuffer::unbind_locked()
return true; return true;
} }
bool FrameBuffer::post(HandleType p_colorbuffer, bool needLock) bool FrameBuffer::post(FrameBufferWindow *window, HandleType p_colorbuffer, bool needLock)
{ {
if (needLock) { if (!window)
return false;
printf("%s window %p\n", __func__, window);
if (needLock)
m_lock.lock(); m_lock.lock();
}
bool ret = false; bool ret;
ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) ); ColorBufferMap::iterator c( m_colorbuffers.find(p_colorbuffer) );
if (c == m_colorbuffers.end()) { if (c == m_colorbuffers.end())
goto EXIT; goto EXIT;
}
m_lastPostedColorBuffer = p_colorbuffer; m_lastPostedColorBuffer = p_colorbuffer;
if (m_subWin) { if (!bindWindow_locked(window))
// bind the subwindow eglSurface goto EXIT;
if (!bindSubwin_locked()) {
ERR("FrameBuffer::post(): eglMakeCurrent failed\n");
goto EXIT;
}
// get the viewport s_gles2.glClear(GL_COLOR_BUFFER_BIT);
GLint vp[4];
s_gles2.glGetIntegerv(GL_VIEWPORT, vp);
// divide by device pixel ratio because windowing coordinates ignore DPR,
// but the framebuffer includes DPR
vp[2] = vp[2] / m_dpr;
vp[3] = vp[3] / m_dpr;
// find the x and y values at the origin when "fully scrolled"
// multiply by 2 because the texture goes from -1 to 1, not 0 to 1
float fx = 2.f * (vp[2] - m_windowWidth) / (float) vp[2];
float fy = 2.f * (vp[3] - m_windowHeight) / (float) vp[3];
// finally, compute translation values
float dx = m_px * fx;
float dy = m_py * fy;
//
// render the color buffer to the window
//
if (m_zRot != 0.0f) {
s_gles2.glClear(GL_COLOR_BUFFER_BIT);
}
ret = (*c).second.cb->post(m_zRot, dx, dy);
if (ret) {
s_egl.eglSwapBuffers(m_eglDisplay, m_eglSurface);
}
// restore previous binding ret = (*c).second.cb->post(0.0f, 0, 0);
unbind_locked(); if (ret) {
} else { s_egl.eglSwapBuffers(m_eglDisplay, window->surface);
// If there is no sub-window, don't display anything, the client will
// rely on m_onPost to get the pixels instead.
ret = true;
} }
// restore previous binding
unbind_locked();
// //
// output FPS statistics // output FPS statistics
// //
...@@ -1131,30 +1002,12 @@ bool FrameBuffer::post(HandleType p_colorbuffer, bool needLock) ...@@ -1131,30 +1002,12 @@ bool FrameBuffer::post(HandleType p_colorbuffer, bool needLock)
} }
} }
//
// Send framebuffer (without FPS overlay) to callback
//
if (m_onPost) {
(*c).second.cb->readback(m_fbImage);
m_onPost(m_onPostContext,
m_framebufferWidth,
m_framebufferHeight,
-1,
GL_RGBA,
GL_UNSIGNED_BYTE,
m_fbImage);
}
EXIT: EXIT:
if (!ret)
printf("post: FAILED\n");
if (needLock) { if (needLock) {
m_lock.unlock(); m_lock.unlock();
} }
return ret; return ret;
} }
bool FrameBuffer::repost() {
if (m_lastPostedColorBuffer) {
return post(m_lastPostedColorBuffer);
}
return false;
}
...@@ -58,6 +58,8 @@ struct FrameBufferCaps { ...@@ -58,6 +58,8 @@ struct FrameBufferCaps {
EGLint eglMinor; EGLint eglMinor;
}; };
struct FrameBufferWindow;
// The FrameBuffer class holds the global state of the emulation library on // The FrameBuffer class holds the global state of the emulation library on
// top of the underlying EGL/GLES implementation. It should probably be // top of the underlying EGL/GLES implementation. It should probably be
// named "Display" instead of "FrameBuffer". // named "Display" instead of "FrameBuffer".
...@@ -76,32 +78,8 @@ public: ...@@ -76,32 +78,8 @@ public:
// Returns true on success, false otherwise. // Returns true on success, false otherwise.
static bool initialize(EGLNativeDisplayType nativeDisplay, int width, int height, bool useSubWindow); static bool initialize(EGLNativeDisplayType nativeDisplay, int width, int height, bool useSubWindow);
// Setup a sub-window to display the content of the emulated GPU FrameBufferWindow* createWindow(int x, int y, int width, int height);
// on-top of an existing UI window. |p_window| is the platform-specific void destroyWindow(FrameBufferWindow *window);
// parent window handle. |wx|, |wy|, |ww| and |wh| are the
// dimensions in pixels of the sub-window, relative to the parent window's
// coordinate. |fbw| and |fbh| are the dimensions used to initialize
// the framebuffer, which may be different from the dimensions of the
// sub-window (in which case scaling will be applied automatically).
// |dpr| is the device pixel ratio of the monitor, which is needed for
// proper panning on high-density displays (like retina)
// |zRot| is a rotation angle in degrees, (clockwise in the Y-upwards GL
// coordinate space).
//
// If a sub-window already exists, this function updates the subwindow
// and framebuffer properties to match the given values.
//
// Return true on success, false otherwise.
//
// NOTE: This can return false for software-only EGL engines like OSMesa.
bool setupSubWindow(FBNativeWindowType p_window,
int wx, int wy,
int ww, int wh,
int fbw, int fbh, float dpr, float zRot);
// Remove the sub-window created by setupSubWindow(), if any.
// Return true on success, false otherwise.
bool removeSubWindow();
// Finalize the instance. // Finalize the instance.
void finalize(); void finalize();
...@@ -113,12 +91,6 @@ public: ...@@ -113,12 +91,6 @@ public:
// Return the capabilities of the underlying display. // Return the capabilities of the underlying display.
const FrameBufferCaps &getCaps() const { return m_caps; } const FrameBufferCaps &getCaps() const { return m_caps; }
// Return the emulated GPU display width in pixels.
int getWidth() const { return m_framebufferWidth; }
// Return the emulated GPU display height in pixels.
int getHeight() const { return m_framebufferHeight; }
// Return the list of configs available from this display. // Return the list of configs available from this display.
const FbConfigList* getConfigs() const { return m_configs; } const FbConfigList* getConfigs() const { return m_configs; }
...@@ -259,36 +231,11 @@ public: ...@@ -259,36 +231,11 @@ public:
// |needLock| is used to indicate whether the operation requires // |needLock| is used to indicate whether the operation requires
// acquiring/releasing the FrameBuffer instance's lock. It should be // acquiring/releasing the FrameBuffer instance's lock. It should be
// false only when called internally. // false only when called internally.
bool post(HandleType p_colorbuffer, bool needLock = true); bool post(FrameBufferWindow *window, HandleType p_colorbuffer, bool needLock = true);
// Re-post the last ColorBuffer that was displayed through post().
// This is useful if you detect that the sub-window content needs to
// be re-displayed for any reason.
bool repost();
// Return the host EGLDisplay used by this instance. // Return the host EGLDisplay used by this instance.
EGLDisplay getDisplay() const { return m_eglDisplay; } EGLDisplay getDisplay() const { return m_eglDisplay; }
// Change the rotation of the displayed GPU sub-window.
void setDisplayRotation(float zRot) {
m_zRot = zRot;
repost();
}
// Changes what coordinate of this framebuffer will be displayed at the
// corner of the GPU sub-window. Specifically, |px| and |py| = 0 means
// align the bottom-left of the framebuffer with the bottom-left of the
// sub-window, and |px| and |py| = 1 means align the top right of the
// framebuffer with the top right of the sub-window. Intermediate values
// interpolate between these states.
void setDisplayTranslation(float px, float py) {
// Sanity check the values to ensure they are between 0 and 1
m_px = px > 1 ? 1 : (px < 0 ? 0 : px);
m_py = py > 1 ? 1 : (py < 0 ? 0 : py);
repost();
}
// Return a TextureDraw instance that can be used with this surfaces // Return a TextureDraw instance that can be used with this surfaces
// and windows created by this instance. // and windows created by this instance.
TextureDraw* getTextureDraw() const { return m_textureDraw; } TextureDraw* getTextureDraw() const { return m_textureDraw; }
...@@ -305,18 +252,11 @@ private: ...@@ -305,18 +252,11 @@ private:
~FrameBuffer(); ~FrameBuffer();
HandleType genHandle(); HandleType genHandle();
bool bindSubwin_locked(); bool bindWindow_locked(FrameBufferWindow *window);
private: private:
static FrameBuffer *s_theFrameBuffer; static FrameBuffer *s_theFrameBuffer;
static HandleType s_nextHandle; static HandleType s_nextHandle;
int m_x;
int m_y;
int m_framebufferWidth;
int m_framebufferHeight;
int m_windowWidth;
int m_windowHeight;
float m_dpr;
bool m_useSubWindow; bool m_useSubWindow;
emugl::Mutex m_lock; emugl::Mutex m_lock;
FbConfigList* m_configs; FbConfigList* m_configs;
...@@ -328,7 +268,6 @@ private: ...@@ -328,7 +268,6 @@ private:
ColorBufferMap m_colorbuffers; ColorBufferMap m_colorbuffers;
ColorBuffer::Helper* m_colorBufferHelper; ColorBuffer::Helper* m_colorBufferHelper;
EGLSurface m_eglSurface;
EGLContext m_eglContext; EGLContext m_eglContext;
EGLSurface m_pbufSurface; EGLSurface m_pbufSurface;
EGLContext m_pbufContext; EGLContext m_pbufContext;
...@@ -336,23 +275,14 @@ private: ...@@ -336,23 +275,14 @@ private:
EGLContext m_prevContext; EGLContext m_prevContext;
EGLSurface m_prevReadSurf; EGLSurface m_prevReadSurf;
EGLSurface m_prevDrawSurf; EGLSurface m_prevDrawSurf;
EGLNativeWindowType m_subWin;
TextureDraw* m_textureDraw; TextureDraw* m_textureDraw;
EGLConfig m_eglConfig; EGLConfig m_eglConfig;
HandleType m_lastPostedColorBuffer; HandleType m_lastPostedColorBuffer;
float m_zRot;
float m_px;
float m_py;
bool m_eglContextInitialized;
int m_statsNumFrames; int m_statsNumFrames;
long long m_statsStartTime; long long m_statsStartTime;
bool m_fpsStats; bool m_fpsStats;
OnPostFn m_onPost;
void* m_onPostContext;
unsigned char* m_fbImage;
const char* m_glVendor; const char* m_glVendor;
const char* m_glRenderer; const char* m_glRenderer;
const char* m_glVersion; const char* m_glVersion;
......
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "LayerManager.h"
#include <algorithm>
namespace {
std::string get_package_name(const std::string &name) {
return name;
}
bool is_layer_blacklisted(const std::string &name) {
static std::vector<std::string> blacklist = {
"BootAnimation",
"StatusBar",
"Sprite",
"KeyguardScrim",
"com.android.launcher/com.android.launcher2.Launcher",
"com.android.settings/com.android.settings.FallbackHome",
"com.android.systemui.ImageWallpaper",
"InputMethod",
};
return std::find(blacklist.begin(), blacklist.end(), name) != blacklist.end();
}
}
std::shared_ptr<LayerManager> LayerManager::get() {
static auto self = std::shared_ptr<LayerManager>{new LayerManager};
return self;
}
LayerManager::LayerManager() {
}
LayerManager::~LayerManager() {
}
void LayerManager::post_layer(const LayerInfo &layer) {
if (is_layer_blacklisted(layer.name)) {
printf("Ignoring blacklisted layer '%s'\n", layer.name.c_str());
return;
}
FrameBufferWindow *window = nullptr;
auto l = layers_.find(layer.name);
if (l != layers_.end()) {
printf("Using existing layer '%s'\n", layer.name.c_str());
window = l->second.window;
l->second.updated = true;
}
else {
printf("New layer '%s' {%d,%d,%d,%d}\n", layer.name.c_str());
window = FrameBuffer::getFB()->createWindow(
layer.display_frame.left,
layer.display_frame.top,
layer.display_frame.right,
layer.display_frame.bottom);
if (!window) {
printf("Failed to create window for layer '%s'\n", layer.name.c_str());
return;
}
layers_.insert({ layer.name, Layer{window, true}});
}
printf("%s: window %p buffer %d\n", __func__, window, layer.buffer_handle);
FrameBuffer::getFB()->post(window, layer.buffer_handle);
}
void LayerManager::finish_cycle() {
for (auto iter = layers_.begin(); iter != layers_.end(); ++iter) {
if (!iter->second.updated) {
FrameBuffer::getFB()->destroyWindow(iter->second.window);
layers_.erase(iter);
}
}
}
/*
* Copyright (C) 2016 Simon Fels <morphis@gravedo.de>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3, as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranties of
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef LAYER_MANAGER_H_
#define LAYER_MANAGER_H_
#include <memory>
#include <map>
#include <vector>
#include <string>
#include "FrameBuffer.h"
struct LayerRect {
int top;
int left;
int right;
int bottom;
};
struct LayerInfo {
std::string name;
LayerRect source_crop;
LayerRect display_frame;
HandleType buffer_handle;
};
class LayerManager {
public:
static std::shared_ptr<LayerManager> get();
~LayerManager();
void post_layer(const LayerInfo &layer);
void finish_cycle();
private:
LayerManager();
struct Layer {
FrameBufferWindow *window;
bool updated;
};
std::map<std::string,Layer> layers_;
};
#endif
...@@ -35,8 +35,6 @@ public: ...@@ -35,8 +35,6 @@ public:
void registerSubWindowHandler(const std::shared_ptr<SubWindowHandler> &handler); void registerSubWindowHandler(const std::shared_ptr<SubWindowHandler> &handler);
typedef void (*SubWindowRepaintCallback)(void*);
// Create a new sub-window that will be used to display the content of the // Create a new sub-window that will be used to display the content of the
// emulated GPU on top of the regular UI window. // emulated GPU on top of the regular UI window.
// |p_window| is the platform-specific handle to the main UI window. // |p_window| is the platform-specific handle to the main UI window.
...@@ -55,25 +53,11 @@ EGLNativeWindowType createSubWindow(FBNativeWindowType p_window, ...@@ -55,25 +53,11 @@ EGLNativeWindowType createSubWindow(FBNativeWindowType p_window,
int x, int x,
int y, int y,
int width, int width,
int height, int height);
SubWindowRepaintCallback repaint_callback,
void* repaint_callback_param);
// Destroy a sub-window previously created through createSubWindow() above. // Destroy a sub-window previously created through createSubWindow() above.
void destroySubWindow(EGLNativeWindowType win); void destroySubWindow(EGLNativeWindowType win);
// Moves a sub-window previously created through createSubWindow() above.
// |p_parent_window| is the platform-specific handle to the main UI window.
// |p_sub_window| is the platform-specific handle to the EGL subwindow.
// |x|,|y|,|width|,|height| are the new location and dimensions of the
// subwindow.
int moveSubWindow(FBNativeWindowType p_parent_window,
EGLNativeWindowType p_sub_window,
int x,
int y,
int width,
int height);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -35,12 +35,8 @@ EGLNativeWindowType createSubWindow(FBNativeWindowType p_window, ...@@ -35,12 +35,8 @@ EGLNativeWindowType createSubWindow(FBNativeWindowType p_window,
int x, int x,
int y, int y,
int width, int width,
int height, int height) {
SubWindowRepaintCallback repaint_callback,
void* repaint_callback_param) {
(void) p_window; (void) p_window;
(void) repaint_callback;
(void) repaint_callback_param;
if (!current_handler) if (!current_handler)
return (EGLNativeWindowType) 0; return (EGLNativeWindowType) 0;
...@@ -54,19 +50,3 @@ void destroySubWindow(EGLNativeWindowType win) { ...@@ -54,19 +50,3 @@ void destroySubWindow(EGLNativeWindowType win) {
return current_handler->destroy_window(win); return current_handler->destroy_window(win);
} }
int moveSubWindow(FBNativeWindowType p_parent_window,
EGLNativeWindowType p_sub_window,
int x,
int y,
int width,
int height) {
(void) p_parent_window;
(void) p_sub_window;
(void) x;
(void) y;
(void) width;
(void) height;
return true;
}
...@@ -21,11 +21,7 @@ ...@@ -21,11 +21,7 @@
#include "TimeUtils.h" #include "TimeUtils.h"
#include "TcpStream.h" #include "TcpStream.h"
#ifdef _WIN32
#include "Win32PipeStream.h"
#else
#include "UnixStream.h" #include "UnixStream.h"
#endif
#include "DispatchTables.h" #include "DispatchTables.h"
...@@ -142,15 +138,6 @@ RENDER_APICALL int RENDER_APIENTRY initOpenGLRenderer( ...@@ -142,15 +138,6 @@ RENDER_APICALL int RENDER_APIENTRY initOpenGLRenderer(
return true; return true;
} }
RENDER_APICALL void RENDER_APIENTRY setPostCallback(
OnPostFn onPost, void* onPostContext) {
if (s_renderWindow) {
s_renderWindow->setPostCallback(onPost, onPostContext);
} else {
ERR("Calling setPostCallback() before creating render window!");
}
}
RENDER_APICALL void RENDER_APIENTRY getHardwareStrings( RENDER_APICALL void RENDER_APIENTRY getHardwareStrings(
const char** vendor, const char** vendor,
const char** renderer, const char** renderer,
...@@ -228,53 +215,7 @@ RENDER_APICALL bool RENDER_APIENTRY destroyOpenGLSubwindow(void) ...@@ -228,53 +215,7 @@ RENDER_APICALL bool RENDER_APIENTRY destroyOpenGLSubwindow(void)
return false; return false;
} }
RENDER_APICALL void RENDER_APIENTRY setOpenGLDisplayRotation(float zRot) #define DEFAULT_STREAM_MODE RENDER_API_STREAM_MODE_UNIX
{
RenderWindow* window = s_renderWindow;
if (window) {
window->setRotation(zRot);
return;
}
// XXX: should be implemented by sending the renderer process
// a request
ERR("%s not implemented for separate renderer process !!!\n",
__FUNCTION__);
}
RENDER_APICALL void RENDER_APIENTRY setOpenGLDisplayTranslation(float px, float py)
{
RenderWindow* window = s_renderWindow;
if (window) {
window->setTranslation(px, py);
return;
}
// XXX: should be implemented by sending the renderer process
// a request
ERR("%s not implemented for separate renderer process !!!\n",
__FUNCTION__);
}
RENDER_APICALL void RENDER_APIENTRY repaintOpenGLDisplay(void)
{
RenderWindow* window = s_renderWindow;
if (window) {
window->repaint();
return;
}
// XXX: should be implemented by sending the renderer process
// a request
ERR("%s not implemented for separate renderer process !!!\n",
__FUNCTION__);
}
/* NOTE: For now, always use TCP mode by default, until the emulator
* has been updated to support Unix and Win32 pipes
*/
#define DEFAULT_STREAM_MODE RENDER_API_STREAM_MODE_TCP
int gRendererStreamMode = DEFAULT_STREAM_MODE; int gRendererStreamMode = DEFAULT_STREAM_MODE;
...@@ -285,11 +226,7 @@ IOStream *createRenderThread(int p_stream_buffer_size, unsigned int clientFlags) ...@@ -285,11 +226,7 @@ IOStream *createRenderThread(int p_stream_buffer_size, unsigned int clientFlags)
if (gRendererStreamMode == RENDER_API_STREAM_MODE_TCP) { if (gRendererStreamMode == RENDER_API_STREAM_MODE_TCP) {
stream = new TcpStream(p_stream_buffer_size); stream = new TcpStream(p_stream_buffer_size);
} else { } else {
#ifdef _WIN32
stream = new Win32PipeStream(p_stream_buffer_size);
#else /* !_WIN32 */
stream = new UnixStream(p_stream_buffer_size); stream = new UnixStream(p_stream_buffer_size);
#endif
} }
if (!stream) { if (!stream) {
...@@ -312,28 +249,3 @@ IOStream *createRenderThread(int p_stream_buffer_size, unsigned int clientFlags) ...@@ -312,28 +249,3 @@ IOStream *createRenderThread(int p_stream_buffer_size, unsigned int clientFlags)
return stream; return stream;
} }
RENDER_APICALL int RENDER_APIENTRY setStreamMode(int mode)
{
switch (mode) {
case RENDER_API_STREAM_MODE_DEFAULT:
mode = DEFAULT_STREAM_MODE;
break;
case RENDER_API_STREAM_MODE_TCP:
break;
#ifndef _WIN32
case RENDER_API_STREAM_MODE_UNIX:
break;
#else /* _WIN32 */
case RENDER_API_STREAM_MODE_PIPE:
break;
#endif /* _WIN32 */
default:
// Invalid stream mode
return false;
}
gRendererStreamMode = mode;
return true;
}
...@@ -20,9 +20,13 @@ ...@@ -20,9 +20,13 @@
#include "FrameBuffer.h" #include "FrameBuffer.h"
#include "RenderThreadInfo.h" #include "RenderThreadInfo.h"
#include "ChecksumCalculatorThreadInfo.h" #include "ChecksumCalculatorThreadInfo.h"
#include "LayerManager.h"
#include "OpenGLESDispatch/EGLDispatch.h" #include "OpenGLESDispatch/EGLDispatch.h"
#include <map>
#include <string>
static const GLint rendererVersion = 1; static const GLint rendererVersion = 1;
static GLint rcGetRendererVersion() static GLint rcGetRendererVersion()
...@@ -156,10 +160,12 @@ static EGLint rcGetFBParam(EGLint param) ...@@ -156,10 +160,12 @@ static EGLint rcGetFBParam(EGLint param)
switch(param) { switch(param) {
case FB_WIDTH: case FB_WIDTH:
ret = fb->getWidth(); // FIXME DISPLAY MANAGER!!
ret = 1920;
break; break;
case FB_HEIGHT: case FB_HEIGHT:
ret = fb->getHeight(); // FIXME DISPLAY MANAGER!!
ret = 1080;
break; break;
case FB_XDPI: case FB_XDPI:
ret = 72; // XXX: should be implemented ret = 72; // XXX: should be implemented
...@@ -306,7 +312,7 @@ static void rcFBPost(uint32_t colorBuffer) ...@@ -306,7 +312,7 @@ static void rcFBPost(uint32_t colorBuffer)
return; return;
} }
fb->post(colorBuffer); fb->post(nullptr, colorBuffer);
} }
static void rcFBSetSwapInterval(EGLint interval) static void rcFBSetSwapInterval(EGLint interval)
...@@ -392,6 +398,56 @@ static void rcSelectChecksumCalculator(uint32_t protocol, uint32_t reserved) { ...@@ -392,6 +398,56 @@ static void rcSelectChecksumCalculator(uint32_t protocol, uint32_t reserved) {
ChecksumCalculatorThreadInfo::setVersion(protocol); ChecksumCalculatorThreadInfo::setVersion(protocol);
} }
int rcGetNumDisplays() {
return 1;
}
int rcGetDisplayWidth(uint32_t display_id) {
printf("%s: display_id=%d\n", __func__, display_id);
return 1920;
}
int rcGetDisplayHeight(uint32_t display_id) {
printf("%s: display_id=%d\n", __func__, display_id);
return 1080;
}
int rcGetDisplayDpiX(uint32_t display_id) {
printf("%s: display_id=%d\n", __func__, display_id);
return 120;
}
int rcGetDisplayDpiY(uint32_t display_id) {
printf("%s: display_id=%d\n", __func__, display_id);
return 120;
}
int rcGetDisplayVsyncPeriod(uint32_t display_id) {
printf("%s: display_id=%d\n", __func__, display_id);
return 1;
}
void rcPostLayer(const char *name, uint32_t color_buffer,
int32_t sourceCropLeft, int32_t sourceCropTop,
int32_t sourceCropRight, int32_t sourceCropBottom,
int32_t displayFrameLeft, int32_t displayFrameTop,
int32_t displayFrameRight, int32_t displayFrameBottom) {
printf("%s: name='%s' color_buffer=%d {%d,%d,%d,%d}, {%d,%d,%d,%d}\n",
__func__, name, color_buffer,
sourceCropLeft, sourceCropTop, sourceCropRight, sourceCropBottom,
displayFrameLeft, displayFrameTop, displayFrameRight, displayFrameBottom);
LayerRect source_crop{sourceCropLeft, sourceCropTop, sourceCropRight, sourceCropBottom};
LayerRect display_frame{displayFrameLeft, displayFrameTop, displayFrameRight, displayFrameBottom};
LayerManager::get()->post_layer({name, source_crop, display_frame, color_buffer});
}
void rcPostAllLayersDone()
{
LayerManager::get()->finish_cycle();
}
void initRenderControlContext(renderControl_decoder_context_t *dec) void initRenderControlContext(renderControl_decoder_context_t *dec)
{ {
dec->rcGetRendererVersion = rcGetRendererVersion; dec->rcGetRendererVersion = rcGetRendererVersion;
...@@ -423,4 +479,12 @@ void initRenderControlContext(renderControl_decoder_context_t *dec) ...@@ -423,4 +479,12 @@ void initRenderControlContext(renderControl_decoder_context_t *dec)
dec->rcCreateClientImage = rcCreateClientImage; dec->rcCreateClientImage = rcCreateClientImage;
dec->rcDestroyClientImage = rcDestroyClientImage; dec->rcDestroyClientImage = rcDestroyClientImage;
dec->rcSelectChecksumCalculator = rcSelectChecksumCalculator; dec->rcSelectChecksumCalculator = rcSelectChecksumCalculator;
dec->rcGetNumDisplays = rcGetNumDisplays;
dec->rcGetDisplayWidth = rcGetDisplayWidth;
dec->rcGetDisplayHeight = rcGetDisplayHeight;
dec->rcGetDisplayDpiX = rcGetDisplayDpiX;
dec->rcGetDisplayDpiY = rcGetDisplayDpiY;
dec->rcGetDisplayVsyncPeriod = rcGetDisplayVsyncPeriod;
dec->rcPostLayer = rcPostLayer;
dec->rcPostAllLayersDone = rcPostAllLayersDone;
} }
...@@ -138,69 +138,6 @@ struct RenderWindowMessage { ...@@ -138,69 +138,6 @@ struct RenderWindowMessage {
result = true; result = true;
break; break;
case CMD_SET_POST_CALLBACK:
D("CMD_SET_POST_CALLBACK\n");
fb = FrameBuffer::getFB();
fb->setPostCallback(msg.set_post_callback.on_post,
msg.set_post_callback.on_post_context);
result = true;
break;
case CMD_SETUP_SUBWINDOW:
D("CMD_SETUP_SUBWINDOW: parent=%p wx=%d wy=%d ww=%d wh=%d fbw=%d fbh=%d dpr=%f rotation=%f\n",
(void*)msg.subwindow.parent,
msg.subwindow.wx,
msg.subwindow.wy,
msg.subwindow.ww,
msg.subwindow.wh,
msg.subwindow.fbw,
msg.subwindow.fbh,
msg.subwindow.dpr,
msg.subwindow.rotation);
result = FrameBuffer::getFB()->setupSubWindow(
msg.subwindow.parent,
msg.subwindow.wx,
msg.subwindow.wy,
msg.subwindow.ww,
msg.subwindow.wh,
msg.subwindow.fbw,
msg.subwindow.fbh,
msg.subwindow.dpr,
msg.subwindow.rotation);
break;
case CMD_REMOVE_SUBWINDOW:
D("CMD_REMOVE_SUBWINDOW\n");
result = FrameBuffer::getFB()->removeSubWindow();
break;
case CMD_SET_ROTATION:
D("CMD_SET_ROTATION rotation=%f\n", msg.rotation);
fb = FrameBuffer::getFB();
if (fb) {
fb->setDisplayRotation(msg.rotation);
result = true;
}
break;
case CMD_SET_TRANSLATION:
D("CMD_SET_TRANSLATION translation=%f,%f\n", msg.trans.px, msg.trans.py);
fb = FrameBuffer::getFB();
if (fb) {
fb->setDisplayTranslation(msg.trans.px, msg.trans.py);
result = true;
}
break;
case CMD_REPAINT:
D("CMD_REPAINT\n");
fb = FrameBuffer::getFB();
if (fb) {
fb->repost();
result = true;
}
break;
default: default:
; ;
} }
...@@ -370,16 +307,6 @@ bool RenderWindow::getHardwareStrings(const char** vendor, ...@@ -370,16 +307,6 @@ bool RenderWindow::getHardwareStrings(const char** vendor,
return true; return true;
} }
void RenderWindow::setPostCallback(OnPostFn onPost, void* onPostContext) {
D("Entering\n");
RenderWindowMessage msg;
msg.cmd = CMD_SET_POST_CALLBACK;
msg.set_post_callback.on_post = onPost;
msg.set_post_callback.on_post_context = onPostContext;
(void) processMessage(msg);
D("Exiting\n");
}
bool RenderWindow::setupSubWindow(FBNativeWindowType window, bool RenderWindow::setupSubWindow(FBNativeWindowType window,
int wx, int wx,
int wy, int wy,
......
...@@ -75,11 +75,6 @@ public: ...@@ -75,11 +75,6 @@ public:
const char** renderer, const char** renderer,
const char** version); 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(OnPostFn onPost, void* onPostContext);
// Start displaying the emulated framebuffer using a sub-window of a // Start displaying the emulated framebuffer using a sub-window of a
// parent |window| id. |wx|, |wy|, |ww| and |wh| are the position // parent |window| id. |wx|, |wy|, |ww| and |wh| are the position
// and dimension of the sub-window, relative to its parent. // and dimension of the sub-window, relative to its parent.
......
...@@ -42,3 +42,6 @@ rcUpdateColorBuffer ...@@ -42,3 +42,6 @@ rcUpdateColorBuffer
rcCloseColorBuffer rcCloseColorBuffer
flag flushOnEncode flag flushOnEncode
rcPostLayer
len name (strlen(name) + 1)
...@@ -27,3 +27,11 @@ GL_ENTRY(int, rcOpenColorBuffer2, uint32_t colorbuffer) ...@@ -27,3 +27,11 @@ GL_ENTRY(int, rcOpenColorBuffer2, uint32_t colorbuffer)
GL_ENTRY(uint32_t, rcCreateClientImage, uint32_t context, EGLenum target, GLuint buffer) GL_ENTRY(uint32_t, rcCreateClientImage, uint32_t context, EGLenum target, GLuint buffer)
GL_ENTRY(int, rcDestroyClientImage, uint32_t image) GL_ENTRY(int, rcDestroyClientImage, uint32_t image)
GL_ENTRY(void, rcSelectChecksumCalculator, uint32_t newProtocol, uint32_t reserved) GL_ENTRY(void, rcSelectChecksumCalculator, uint32_t newProtocol, uint32_t reserved)
GL_ENTRY(int, rcGetNumDisplays)
GL_ENTRY(int, rcGetDisplayWidth, uint32_t displayId)
GL_ENTRY(int, rcGetDisplayHeight, uint32_t displayId)
GL_ENTRY(int, rcGetDisplayDpiX, uint32_t displayId)
GL_ENTRY(int, rcGetDisplayDpiY, uint32_t displayId)
GL_ENTRY(int, rcGetDisplayVsyncPeriod, uint32_t displayId)
GL_ENTRY(void, rcPostLayer, const char* name, uint32_t colorBuffer, int32_t sourceCropLeft, int32_t sourceCropTop, int32_t sourceCropRight, int32_t sourceCropBottom, int32_t displayFrameLeft, int32_t displayFrameTop, int32_t displayFrameRight, int32_t displayFrameBottom)
GL_ENTRY(void, rcPostAllLayersDone)
uint32_t 32 0x%08x uint32_t 32 0x%08x
int32_t 32 0x%08x
EGLint 32 0x%08x EGLint 32 0x%08x
GLint 32 0x%08x GLint 32 0x%08x
GLuint 32 0x%08x GLuint 32 0x%08x
...@@ -9,3 +10,4 @@ EGLint* 32 0x%08x ...@@ -9,3 +10,4 @@ EGLint* 32 0x%08x
GLint* 32 0x%08x GLint* 32 0x%08x
GLuint* 32 0x%08x GLuint* 32 0x%08x
void* 32 0x%08x void* 32 0x%08x
char* 32 0x%08x
...@@ -140,7 +140,7 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory) ...@@ -140,7 +140,7 @@ anbox::cmds::Run::Run(const BusFactory& bus_factory)
// { qemud_connector->socket_file(), "/dev/qemud" }, // { qemud_connector->socket_file(), "/dev/qemud" },
{ qemu_pipe_connector->socket_file(), "/dev/qemu_pipe" }, { qemu_pipe_connector->socket_file(), "/dev/qemu_pipe" },
{ bridge_connector->socket_file(), "/dev/anbox_bridge" }, { bridge_connector->socket_file(), "/dev/anbox_bridge" },
{ config::host_input_device_path(), "/dev/input" }, { "/dev/input", "/dev/input" },
{ "/dev/binder", "/dev/binder" }, { "/dev/binder", "/dev/binder" },
{ "/dev/ashmem", "/dev/ashmem" }, { "/dev/ashmem", "/dev/ashmem" },
}; };
......
...@@ -45,13 +45,11 @@ GLRendererServer::GLRendererServer(const std::shared_ptr<WindowCreator> &window_ ...@@ -45,13 +45,11 @@ GLRendererServer::GLRendererServer(const std::shared_ptr<WindowCreator> &window_
if (!initLibrary()) if (!initLibrary())
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize OpenGL renderer")); BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize OpenGL renderer"));
setStreamMode(RENDER_API_STREAM_MODE_UNIX);
registerSubWindowHandler(window_creator_); registerSubWindowHandler(window_creator_);
} }
GLRendererServer::~GLRendererServer() { GLRendererServer::~GLRendererServer() {
destroyOpenGLSubwindow(); // destroyOpenGLSubwindow();
stopOpenGLRenderer(); stopOpenGLRenderer();
} }
...@@ -84,11 +82,13 @@ void GLRendererServer::start() { ...@@ -84,11 +82,13 @@ void GLRendererServer::start() {
socket_path_ = server_addr; socket_path_ = server_addr;
#if 0
// Create the window we use for rendering the output we get from the // Create the window we use for rendering the output we get from the
// Android container. This will internally construct a Mir surface // Android container. This will internally construct a Mir surface
// and use the host EGL/GLES libraries for rendering. // and use the host EGL/GLES libraries for rendering.
if (!showOpenGLSubwindow(0, 0, 0, width, height, width, height, 1.0f, 0)) if (!showOpenGLSubwindow(0, 0, 0, width, height, width, height, 1.0f, 0))
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to setup GL based window")); BOOST_THROW_EXCEPTION(std::runtime_error("Failed to setup GL based window"));
#endif
} }
std::string GLRendererServer::socket_path() const { std::string GLRendererServer::socket_path() const {
......
...@@ -54,7 +54,7 @@ void BootPropertiesMessageProcessor::list_properties() { ...@@ -54,7 +54,7 @@ void BootPropertiesMessageProcessor::list_properties() {
// TODO(morphis): Using HDPI here for now but should be adjusted to the device // TODO(morphis): Using HDPI here for now but should be adjusted to the device
// we're running on. // we're running on.
utils::string_format("ro.sf.lcd_density=%d", static_cast<int>(graphics::DensityType::high)), utils::string_format("ro.sf.lcd_density=%d", static_cast<int>(graphics::DensityType::medium)),
// Disable on-screen virtual keys as we can use the hardware keyboard // Disable on-screen virtual keys as we can use the hardware keyboard
"qemu.hw.mainkeys=1", "qemu.hw.mainkeys=1",
......
此差异已折叠。
...@@ -26,26 +26,15 @@ ...@@ -26,26 +26,15 @@
#include <SDL.h> #include <SDL.h>
namespace anbox { namespace anbox {
namespace input {
class Manager;
class Device;
class Event;
} // namespace input
namespace ubuntu { namespace ubuntu {
class Window { class Window {
public: public:
Window(const std::shared_ptr<input::Manager> &input_manager, Window(int x, int y, int width, int height);
int width, int height);
~Window(); ~Window();
void process_input_event(const SDL_Event &event);
EGLNativeWindowType native_window() const; EGLNativeWindowType native_window() const;
private: private:
std::shared_ptr<input::Device> touchpanel_;
std::shared_ptr<input::Device> pointer_;
std::shared_ptr<input::Device> keyboard_;
EGLNativeDisplayType native_display_; EGLNativeDisplayType native_display_;
EGLNativeWindowType native_window_; EGLNativeWindowType native_window_;
SDL_Window *window_; SDL_Window *window_;
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include "anbox/ubuntu/window_creator.h" #include "anbox/ubuntu/window_creator.h"
#include "anbox/ubuntu/window.h" #include "anbox/ubuntu/window.h"
#include "anbox/input/manager.h"
#include "anbox/input/device.h"
#include "anbox/logger.h" #include "anbox/logger.h"
#include <boost/throw_exception.hpp> #include <boost/throw_exception.hpp>
...@@ -35,6 +37,16 @@ WindowCreator::WindowCreator(const std::shared_ptr<input::Manager> &input_manage ...@@ -35,6 +37,16 @@ WindowCreator::WindowCreator(const std::shared_ptr<input::Manager> &input_manage
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0)
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize SDL")); BOOST_THROW_EXCEPTION(std::runtime_error("Failed to initialize SDL"));
#if 0
SDL_DisplayMode display_mode;
// FIXME statically just check the first (primary) display for its mode;
// once we get multi-monitor support we need to do this better.
if (SDL_GetCurrentDisplayMode(0, &display_mode) == 0) {
display_info_.horizontal_resolution = display_mode.w;
display_info_.vertical_resolution = display_mode.h;
}
#endif
event_thread_ = std::thread(&WindowCreator::process_events, this); event_thread_ = std::thread(&WindowCreator::process_events, this);
SDL_DisplayMode display_mode; SDL_DisplayMode display_mode;
...@@ -69,18 +81,6 @@ void WindowCreator::process_events() { ...@@ -69,18 +81,6 @@ void WindowCreator::process_events() {
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:
process_window_event(event); process_window_event(event);
break; break;
case SDL_FINGERUP:
case SDL_FINGERMOTION:
case SDL_FINGERDOWN:
case SDL_MOUSEMOTION:
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEWHEEL:
case SDL_KEYDOWN:
case SDL_KEYUP:
if (current_window_)
current_window_->process_input_event(event);
break;
} }
} }
} }
...@@ -88,17 +88,11 @@ void WindowCreator::process_events() { ...@@ -88,17 +88,11 @@ void WindowCreator::process_events() {
EGLNativeWindowType WindowCreator::create_window(int x, int y, int width, int height) EGLNativeWindowType WindowCreator::create_window(int x, int y, int width, int height)
try { try {
if (windows_.size() == 1) { auto window = std::make_shared<Window>(x, y, width, height);
WARNING("Tried to create another window but we currently only allow one");
return 0;
}
auto window = std::make_shared<Window>(input_manager_, width, height);
if (not window) if (not window)
BOOST_THROW_EXCEPTION(std::bad_alloc()); BOOST_THROW_EXCEPTION(std::bad_alloc());
windows_.insert({window->native_window(), window}); windows_.insert({window->native_window(), window});
current_window_ = window;
return window->native_window(); return window->native_window();
} }
......
...@@ -27,6 +27,9 @@ ...@@ -27,6 +27,9 @@
#include <SDL.h> #include <SDL.h>
namespace anbox { namespace anbox {
namespace input {
class Device;
} // namespace input
namespace ubuntu { namespace ubuntu {
class MirDisplayConnection; class MirDisplayConnection;
class Window; class Window;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册