Implement support for host side multi-window management
This commit is contained in:
parent
c4e1e291ac
commit
fbc8b984f2
23 changed files with 428 additions and 983 deletions
|
|
@ -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 @@
|
||||||
#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 {
|
||||||
};
|
};
|
||||||
|
|
||||||
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,
|
||||||
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) {
|
||||||
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
|
||||||
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
|
||||||
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
|
||||||
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)
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
||||||
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)
|
struct FrameBufferWindow {
|
||||||
{
|
EGLNativeWindowType native_window = 0;
|
||||||
emugl::Mutex::AutoLock mutex(m_lock);
|
EGLSurface surface = EGL_NO_SURFACE;
|
||||||
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) {
|
|
||||||
auto fb = static_cast<FrameBuffer*>(param);
|
|
||||||
fb->repost();
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
m_y = wy;
|
|
||||||
m_windowWidth = ww;
|
|
||||||
m_windowHeight = wh;
|
|
||||||
|
|
||||||
success = ::moveSubWindow(m_nativeWindow, m_subWin,
|
|
||||||
m_x, m_y, m_windowWidth, m_windowHeight);
|
|
||||||
|
|
||||||
// Otherwise, ensure that at least viewport parameters are properly updated.
|
|
||||||
} else {
|
|
||||||
success = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (success) {
|
if (!bindWindow_locked(window)) {
|
||||||
// Subwin creation or movement was successful,
|
destroyWindow(window);
|
||||||
// update viewport and z rotation and draw
|
m_lock.unlock();
|
||||||
// the last posted color buffer.
|
return nullptr;
|
||||||
s_gles2.glViewport(0, 0, fbw * dpr, fbh * dpr);
|
}
|
||||||
m_dpr = dpr;
|
|
||||||
m_zRot = zRot;
|
s_gles2.glViewport(0, 0, width, height);
|
||||||
if (m_lastPostedColorBuffer) {
|
|
||||||
post(m_lastPostedColorBuffer, false);
|
|
||||||
} else {
|
|
||||||
s_gles2.glClear(GL_COLOR_BUFFER_BIT |
|
s_gles2.glClear(GL_COLOR_BUFFER_BIT |
|
||||||
GL_DEPTH_BUFFER_BIT |
|
GL_DEPTH_BUFFER_BIT |
|
||||||
GL_STENCIL_BUFFER_BIT);
|
GL_STENCIL_BUFFER_BIT);
|
||||||
s_egl.eglSwapBuffers(m_eglDisplay, m_eglSurface);
|
s_egl.eglSwapBuffers(m_eglDisplay, window->surface);
|
||||||
}
|
|
||||||
}
|
|
||||||
unbind_locked();
|
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()
|
||||||
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,63 +957,36 @@ 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
|
|
||||||
if (!bindSubwin_locked()) {
|
|
||||||
ERR("FrameBuffer::post(): eglMakeCurrent failed\n");
|
|
||||||
goto EXIT;
|
goto EXIT;
|
||||||
}
|
|
||||||
|
|
||||||
// get the viewport
|
|
||||||
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);
|
s_gles2.glClear(GL_COLOR_BUFFER_BIT);
|
||||||
}
|
|
||||||
ret = (*c).second.cb->post(m_zRot, dx, dy);
|
ret = (*c).second.cb->post(0.0f, 0, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
s_egl.eglSwapBuffers(m_eglDisplay, m_eglSurface);
|
s_egl.eglSwapBuffers(m_eglDisplay, window->surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore previous binding
|
// restore previous binding
|
||||||
unbind_locked();
|
unbind_locked();
|
||||||
} else {
|
|
||||||
// If there is no sub-window, don't display anything, the client will
|
|
||||||
// rely on m_onPost to get the pixels instead.
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// output FPS statistics
|
// output FPS statistics
|
||||||
|
|
@ -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 {
|
||||||
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:
|
||||||
// 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:
|
||||||
// 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:
|
||||||
// |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:
|
||||||
~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:
|
||||||
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:
|
||||||
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;
|
||||||
|
|
|
||||||
92
external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp
vendored
Normal file
92
external/android-emugl/host/libs/libOpenglRender/LayerManager.cpp
vendored
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
63
external/android-emugl/host/libs/libOpenglRender/LayerManager.h
vendored
Normal file
63
external/android-emugl/host/libs/libOpenglRender/LayerManager.h
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* 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:
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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) {
|
||||||
|
|
||||||
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 @@
|
||||||
#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(
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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 @@
|
||||||
#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)
|
||||||
|
|
||||||
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)
|
||||||
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) {
|
||||||
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)
|
||||||
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 {
|
||||||
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,
|
||||||
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:
|
||||||
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
|
||||||
|
|
||||||
rcCloseColorBuffer
|
rcCloseColorBuffer
|
||||||
flag flushOnEncode
|
flag flushOnEncode
|
||||||
|
|
||||||
|
rcPostLayer
|
||||||
|
len name (strlen(name) + 1)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
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
|
||||||
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)
|
||||||
// { 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_
|
||||||
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() {
|
||||||
|
|
||||||
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() {
|
||||||
|
|
||||||
// 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",
|
||||||
|
|
|
||||||
|
|
@ -16,338 +16,26 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#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>
|
||||||
|
|
||||||
#include <SDL_syswm.h>
|
#include <SDL_syswm.h>
|
||||||
|
|
||||||
namespace {
|
|
||||||
class SlotFingerMapper {
|
|
||||||
public:
|
|
||||||
int find_or_create(SDL_FingerID id) {
|
|
||||||
auto iter = std::find(slots_.begin(), slots_.end(), id);
|
|
||||||
if (iter != slots_.end())
|
|
||||||
return std::distance(slots_.begin(), iter);
|
|
||||||
|
|
||||||
std::vector<int>::size_type i;
|
|
||||||
for(i = 0;i < slots_.size();i++) {
|
|
||||||
if (slots_[i] == -1) {
|
|
||||||
slots_[i] = id;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
slots_.resize(slots_.size() + 1);
|
|
||||||
slots_[slots_.size() - 1] = id;
|
|
||||||
|
|
||||||
return slots_.size() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void erase(SDL_FingerID id)
|
|
||||||
{
|
|
||||||
auto it = std::find(slots_.begin(), slots_.end(), id);
|
|
||||||
|
|
||||||
if (it != slots_.end()) {
|
|
||||||
auto index = std::distance(slots_.begin(), it);
|
|
||||||
slots_[index] = -1;
|
|
||||||
if (index == slots_.size()-1) {
|
|
||||||
while (slots_[index] == -1) {
|
|
||||||
slots_.resize(index);
|
|
||||||
index--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<SDL_FingerID> slots_;
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::array<SDL_Scancode, 249> kKeycodes {{
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_RESERVED 0 */
|
|
||||||
SDL_SCANCODE_ESCAPE, /* KEY_ESC 1 */
|
|
||||||
SDL_SCANCODE_1, /* KEY_1 2 */
|
|
||||||
SDL_SCANCODE_2, /* KEY_2 3 */
|
|
||||||
SDL_SCANCODE_3, /* KEY_3 4 */
|
|
||||||
SDL_SCANCODE_4, /* KEY_4 5 */
|
|
||||||
SDL_SCANCODE_5, /* KEY_5 6 */
|
|
||||||
SDL_SCANCODE_6, /* KEY_6 7 */
|
|
||||||
SDL_SCANCODE_7, /* KEY_7 8 */
|
|
||||||
SDL_SCANCODE_8, /* KEY_8 9 */
|
|
||||||
SDL_SCANCODE_9, /* KEY_9 10 */
|
|
||||||
SDL_SCANCODE_0, /* KEY_0 11 */
|
|
||||||
SDL_SCANCODE_MINUS, /* KEY_MINUS 12 */
|
|
||||||
SDL_SCANCODE_EQUALS, /* KEY_EQUAL 13 */
|
|
||||||
SDL_SCANCODE_BACKSPACE, /* KEY_BACKSPACE 14 */
|
|
||||||
SDL_SCANCODE_TAB, /* KEY_TAB 15 */
|
|
||||||
SDL_SCANCODE_Q, /* KEY_Q 16 */
|
|
||||||
SDL_SCANCODE_W, /* KEY_W 17 */
|
|
||||||
SDL_SCANCODE_E, /* KEY_E 18 */
|
|
||||||
SDL_SCANCODE_R, /* KEY_R 19 */
|
|
||||||
SDL_SCANCODE_T, /* KEY_T 20 */
|
|
||||||
SDL_SCANCODE_Y, /* KEY_Y 21 */
|
|
||||||
SDL_SCANCODE_U, /* KEY_U 22 */
|
|
||||||
SDL_SCANCODE_I, /* KEY_I 23 */
|
|
||||||
SDL_SCANCODE_O, /* KEY_O 24 */
|
|
||||||
SDL_SCANCODE_P, /* KEY_P 25 */
|
|
||||||
SDL_SCANCODE_LEFTBRACKET, /* KEY_LEFTBRACE 26 */
|
|
||||||
SDL_SCANCODE_RIGHTBRACKET, /* KEY_RIGHTBRACE 27 */
|
|
||||||
SDL_SCANCODE_RETURN, /* KEY_ENTER 28 */
|
|
||||||
SDL_SCANCODE_LCTRL, /* KEY_LEFTCTRL 29 */
|
|
||||||
SDL_SCANCODE_A, /* KEY_A 30 */
|
|
||||||
SDL_SCANCODE_S, /* KEY_S 31 */
|
|
||||||
SDL_SCANCODE_D, /* KEY_D 32 */
|
|
||||||
SDL_SCANCODE_F, /* KEY_F 33 */
|
|
||||||
SDL_SCANCODE_G, /* KEY_G 34 */
|
|
||||||
SDL_SCANCODE_H, /* KEY_H 35 */
|
|
||||||
SDL_SCANCODE_J, /* KEY_J 36 */
|
|
||||||
SDL_SCANCODE_K, /* KEY_K 37 */
|
|
||||||
SDL_SCANCODE_L, /* KEY_L 38 */
|
|
||||||
SDL_SCANCODE_SEMICOLON, /* KEY_SEMICOLON 39 */
|
|
||||||
SDL_SCANCODE_APOSTROPHE, /* KEY_APOSTROPHE 40 */
|
|
||||||
SDL_SCANCODE_GRAVE, /* KEY_GRAVE 41 */
|
|
||||||
SDL_SCANCODE_LSHIFT, /* KEY_LEFTSHIFT 42 */
|
|
||||||
SDL_SCANCODE_BACKSLASH, /* KEY_BACKSLASH 43 */
|
|
||||||
SDL_SCANCODE_Z, /* KEY_Z 44 */
|
|
||||||
SDL_SCANCODE_X, /* KEY_X 45 */
|
|
||||||
SDL_SCANCODE_C, /* KEY_C 46 */
|
|
||||||
SDL_SCANCODE_V, /* KEY_V 47 */
|
|
||||||
SDL_SCANCODE_B, /* KEY_B 48 */
|
|
||||||
SDL_SCANCODE_N, /* KEY_N 49 */
|
|
||||||
SDL_SCANCODE_M, /* KEY_M 50 */
|
|
||||||
SDL_SCANCODE_COMMA, /* KEY_COMMA 51 */
|
|
||||||
SDL_SCANCODE_PERIOD, /* KEY_DOT 52 */
|
|
||||||
SDL_SCANCODE_SLASH, /* KEY_SLASH 53 */
|
|
||||||
SDL_SCANCODE_RSHIFT, /* KEY_RIGHTSHIFT 54 */
|
|
||||||
SDL_SCANCODE_KP_MULTIPLY, /* KEY_KPASTERISK 55 */
|
|
||||||
SDL_SCANCODE_LALT, /* KEY_LEFTALT 56 */
|
|
||||||
SDL_SCANCODE_SPACE, /* KEY_SPACE 57 */
|
|
||||||
SDL_SCANCODE_CAPSLOCK, /* KEY_CAPSLOCK 58 */
|
|
||||||
SDL_SCANCODE_F1, /* KEY_F1 59 */
|
|
||||||
SDL_SCANCODE_F2, /* KEY_F2 60 */
|
|
||||||
SDL_SCANCODE_F3, /* KEY_F3 61 */
|
|
||||||
SDL_SCANCODE_F4, /* KEY_F4 62 */
|
|
||||||
SDL_SCANCODE_F5, /* KEY_F5 63 */
|
|
||||||
SDL_SCANCODE_F6, /* KEY_F6 64 */
|
|
||||||
SDL_SCANCODE_F7, /* KEY_F7 65 */
|
|
||||||
SDL_SCANCODE_F8, /* KEY_F8 66 */
|
|
||||||
SDL_SCANCODE_F9, /* KEY_F9 67 */
|
|
||||||
SDL_SCANCODE_F10, /* KEY_F10 68 */
|
|
||||||
SDL_SCANCODE_NUMLOCKCLEAR, /* KEY_NUMLOCK 69 */
|
|
||||||
SDL_SCANCODE_SCROLLLOCK, /* KEY_SCROLLLOCK 70 */
|
|
||||||
SDL_SCANCODE_KP_7, /* KEY_KP7 71 */
|
|
||||||
SDL_SCANCODE_KP_8, /* KEY_KP8 72 */
|
|
||||||
SDL_SCANCODE_KP_9, /* KEY_KP9 73 */
|
|
||||||
SDL_SCANCODE_KP_MINUS, /* KEY_KPMINUS 74 */
|
|
||||||
SDL_SCANCODE_KP_4, /* KEY_KP4 75 */
|
|
||||||
SDL_SCANCODE_KP_5, /* KEY_KP5 76 */
|
|
||||||
SDL_SCANCODE_KP_6, /* KEY_KP6 77 */
|
|
||||||
SDL_SCANCODE_KP_PLUS, /* KEY_KPPLUS 78 */
|
|
||||||
SDL_SCANCODE_KP_1, /* KEY_KP1 79 */
|
|
||||||
SDL_SCANCODE_KP_2, /* KEY_KP2 80 */
|
|
||||||
SDL_SCANCODE_KP_3, /* KEY_KP3 81 */
|
|
||||||
SDL_SCANCODE_KP_0, /* KEY_KP0 82 */
|
|
||||||
SDL_SCANCODE_KP_PERIOD, /* KEY_KPDOT 83 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* 84 */
|
|
||||||
SDL_SCANCODE_LANG5, /* KEY_ZENKAKUHANKAKU 85 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_102ND 86 */
|
|
||||||
SDL_SCANCODE_F11, /* KEY_F11 87 */
|
|
||||||
SDL_SCANCODE_F12, /* KEY_F12 88 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_RO 89 */
|
|
||||||
SDL_SCANCODE_LANG3, /* KEY_KATAKANA 90 */
|
|
||||||
SDL_SCANCODE_LANG4, /* KEY_HIRAGANA 91 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_HENKAN 92 */
|
|
||||||
SDL_SCANCODE_LANG3, /* KEY_KATAKANAHIRAGANA 93 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_MUHENKAN 94 */
|
|
||||||
SDL_SCANCODE_KP_COMMA, /* KEY_KPJPCOMMA 95 */
|
|
||||||
SDL_SCANCODE_KP_ENTER, /* KEY_KPENTER 96 */
|
|
||||||
SDL_SCANCODE_RCTRL, /* KEY_RIGHTCTRL 97 */
|
|
||||||
SDL_SCANCODE_KP_DIVIDE, /* KEY_KPSLASH 98 */
|
|
||||||
SDL_SCANCODE_SYSREQ, /* KEY_SYSRQ 99 */
|
|
||||||
SDL_SCANCODE_RALT, /* KEY_RIGHTALT 100 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_LINEFEED 101 */
|
|
||||||
SDL_SCANCODE_HOME, /* KEY_HOME 102 */
|
|
||||||
SDL_SCANCODE_UP, /* KEY_UP 103 */
|
|
||||||
SDL_SCANCODE_PAGEUP, /* KEY_PAGEUP 104 */
|
|
||||||
SDL_SCANCODE_LEFT, /* KEY_LEFT 105 */
|
|
||||||
SDL_SCANCODE_RIGHT, /* KEY_RIGHT 106 */
|
|
||||||
SDL_SCANCODE_END, /* KEY_END 107 */
|
|
||||||
SDL_SCANCODE_DOWN, /* KEY_DOWN 108 */
|
|
||||||
SDL_SCANCODE_PAGEDOWN, /* KEY_PAGEDOWN 109 */
|
|
||||||
SDL_SCANCODE_INSERT, /* KEY_INSERT 110 */
|
|
||||||
SDL_SCANCODE_DELETE, /* KEY_DELETE 111 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_MACRO 112 */
|
|
||||||
SDL_SCANCODE_MUTE, /* KEY_MUTE 113 */
|
|
||||||
SDL_SCANCODE_VOLUMEDOWN, /* KEY_VOLUMEDOWN 114 */
|
|
||||||
SDL_SCANCODE_VOLUMEUP, /* KEY_VOLUMEUP 115 */
|
|
||||||
SDL_SCANCODE_POWER, /* KEY_POWER 116 SC System Power Down */
|
|
||||||
SDL_SCANCODE_KP_EQUALS, /* KEY_KPEQUAL 117 */
|
|
||||||
SDL_SCANCODE_KP_MINUS, /* KEY_KPPLUSMINUS 118 */
|
|
||||||
SDL_SCANCODE_PAUSE, /* KEY_PAUSE 119 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_SCALE 120 AL Compiz Scale (Expose) */
|
|
||||||
SDL_SCANCODE_KP_COMMA, /* KEY_KPCOMMA 121 */
|
|
||||||
SDL_SCANCODE_LANG1, /* KEY_HANGEUL,KEY_HANGUEL 122 */
|
|
||||||
SDL_SCANCODE_LANG2, /* KEY_HANJA 123 */
|
|
||||||
SDL_SCANCODE_INTERNATIONAL3,/* KEY_YEN 124 */
|
|
||||||
SDL_SCANCODE_LGUI, /* KEY_LEFTMETA 125 */
|
|
||||||
SDL_SCANCODE_RGUI, /* KEY_RIGHTMETA 126 */
|
|
||||||
SDL_SCANCODE_APPLICATION, /* KEY_COMPOSE 127 */
|
|
||||||
SDL_SCANCODE_STOP, /* KEY_STOP 128 AC Stop */
|
|
||||||
SDL_SCANCODE_AGAIN, /* KEY_AGAIN 129 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_PROPS 130 AC Properties */
|
|
||||||
SDL_SCANCODE_UNDO, /* KEY_UNDO 131 AC Undo */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_FRONT 132 */
|
|
||||||
SDL_SCANCODE_COPY, /* KEY_COPY 133 AC Copy */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_OPEN 134 AC Open */
|
|
||||||
SDL_SCANCODE_PASTE, /* KEY_PASTE 135 AC Paste */
|
|
||||||
SDL_SCANCODE_FIND, /* KEY_FIND 136 AC Search */
|
|
||||||
SDL_SCANCODE_CUT, /* KEY_CUT 137 AC Cut */
|
|
||||||
SDL_SCANCODE_HELP, /* KEY_HELP 138 AL Integrated Help Center */
|
|
||||||
SDL_SCANCODE_MENU, /* KEY_MENU 139 Menu (show menu) */
|
|
||||||
SDL_SCANCODE_CALCULATOR, /* KEY_CALC 140 AL Calculator */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_SETUP 141 */
|
|
||||||
SDL_SCANCODE_SLEEP, /* KEY_SLEEP 142 SC System Sleep */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_WAKEUP 143 System Wake Up */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_FILE 144 AL Local Machine Browser */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_SENDFILE 145 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_DELETEFILE 146 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_XFER 147 */
|
|
||||||
SDL_SCANCODE_APP1, /* KEY_PROG1 148 */
|
|
||||||
SDL_SCANCODE_APP1, /* KEY_PROG2 149 */
|
|
||||||
SDL_SCANCODE_WWW, /* KEY_WWW 150 AL Internet Browser */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_MSDOS 151 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_COFFEE,KEY_SCREENLOCK 152 AL Terminal Lock/Screensaver */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_DIRECTION 153 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_CYCLEWINDOWS 154 */
|
|
||||||
SDL_SCANCODE_MAIL, /* KEY_MAIL 155 */
|
|
||||||
SDL_SCANCODE_AC_BOOKMARKS, /* KEY_BOOKMARKS 156 AC Bookmarks */
|
|
||||||
SDL_SCANCODE_COMPUTER, /* KEY_COMPUTER 157 */
|
|
||||||
SDL_SCANCODE_AC_BACK, /* KEY_BACK 158 AC Back */
|
|
||||||
SDL_SCANCODE_AC_FORWARD, /* KEY_FORWARD 159 AC Forward */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_CLOSECD 160 */
|
|
||||||
SDL_SCANCODE_EJECT, /* KEY_EJECTCD 161 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_EJECTCLOSECD 162 */
|
|
||||||
SDL_SCANCODE_AUDIONEXT, /* KEY_NEXTSONG 163 */
|
|
||||||
SDL_SCANCODE_AUDIOPLAY, /* KEY_PLAYPAUSE 164 */
|
|
||||||
SDL_SCANCODE_AUDIOPREV, /* KEY_PREVIOUSSONG 165 */
|
|
||||||
SDL_SCANCODE_AUDIOSTOP, /* KEY_STOPCD 166 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_RECORD 167 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_REWIND 168 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_PHONE 169 Media Select Telephone */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_ISO 170 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_CONFIG 171 AL Consumer Control Configuration */
|
|
||||||
SDL_SCANCODE_AC_HOME, /* KEY_HOMEPAGE 172 AC Home */
|
|
||||||
SDL_SCANCODE_AC_REFRESH, /* KEY_REFRESH 173 AC Refresh */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_EXIT 174 AC Exit */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_MOVE 175 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_EDIT 176 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_SCROLLUP 177 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_SCROLLDOWN 178 */
|
|
||||||
SDL_SCANCODE_KP_LEFTPAREN, /* KEY_KPLEFTPAREN 179 */
|
|
||||||
SDL_SCANCODE_KP_RIGHTPAREN, /* KEY_KPRIGHTPAREN 180 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_NEW 181 AC New */
|
|
||||||
SDL_SCANCODE_AGAIN, /* KEY_REDO 182 AC Redo/Repeat */
|
|
||||||
SDL_SCANCODE_F13, /* KEY_F13 183 */
|
|
||||||
SDL_SCANCODE_F14, /* KEY_F14 184 */
|
|
||||||
SDL_SCANCODE_F15, /* KEY_F15 185 */
|
|
||||||
SDL_SCANCODE_F16, /* KEY_F16 186 */
|
|
||||||
SDL_SCANCODE_F17, /* KEY_F17 187 */
|
|
||||||
SDL_SCANCODE_F18, /* KEY_F18 188 */
|
|
||||||
SDL_SCANCODE_F19, /* KEY_F19 189 */
|
|
||||||
SDL_SCANCODE_F20, /* KEY_F20 190 */
|
|
||||||
SDL_SCANCODE_F21, /* KEY_F21 191 */
|
|
||||||
SDL_SCANCODE_F22, /* KEY_F22 192 */
|
|
||||||
SDL_SCANCODE_F23, /* KEY_F23 193 */
|
|
||||||
SDL_SCANCODE_F24, /* KEY_F24 194 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* 195 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* 196 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* 197 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* 198 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* 199 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_PLAYCD 200 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_PAUSECD 201 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_PROG3 202 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_PROG4 203 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_DASHBOARD 204 AL Dashboard */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_SUSPEND 205 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_CLOSE 206 AC Close */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_PLAY 207 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_FASTFORWARD 208 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_BASSBOOST 209 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_PRINT 210 AC Print */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_HP 211 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_CAMERA 212 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_SOUND 213 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_QUESTION 214 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_EMAIL 215 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_CHAT 216 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_SEARCH 217 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_CONNECT 218 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_FINANCE 219 AL Checkbook/Finance */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_SPORT 220 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_SHOP 221 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_ALTERASE 222 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_CANCEL 223 AC Cancel */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESSDOWN 224 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESSUP 225 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_MEDIA 226 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_SWITCHVIDEOMODE 227 Cycle between available video outputs (Monitor/LCD/TV-out/etc) */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_KBDILLUMTOGGLE 228 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_KBDILLUMDOWN 229 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_KBDILLUMUP 230 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_SEND 231 AC Send */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_REPLY 232 AC Reply */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_FORWARDMAIL 233 AC Forward Msg */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_SAVE 234 AC Save */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_DOCUMENTS 235 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_BATTERY 236 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_BLUETOOTH 237 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_WLAN 238 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_UWB 239 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_UNKNOWN 240 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_VIDEO_NEXT 241 drive next video source */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_VIDEO_PREV 242 drive previous video source */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESS_CYCLE 243 brightness up, after max is min */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESS_ZERO 244 brightness off, use ambient */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_DISPLAY_OFF 245 display device to off state */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_WIMAX 246 */
|
|
||||||
SDL_SCANCODE_UNKNOWN, /* KEY_RFKILL 247 Key that controls all radios */
|
|
||||||
SDL_SCANCODE_UNKNOWN /* KEY_MICMUTE 248 Mute / unmute the microphone */
|
|
||||||
}};
|
|
||||||
|
|
||||||
std::uint16_t convert_sdl_scancode_to_evdev(const SDL_Scancode &scan_code) {
|
|
||||||
for (std::uint16_t n = 0; n < kKeycodes.size(); n++) {
|
|
||||||
if (kKeycodes[n] == scan_code)
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
return KEY_RESERVED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace anbox {
|
namespace anbox {
|
||||||
namespace ubuntu {
|
namespace ubuntu {
|
||||||
Window::Window(const std::shared_ptr<input::Manager> &input_manager,
|
Window::Window(int x, int y, int width, int height) :
|
||||||
int width, int height) :
|
|
||||||
native_display_(0),
|
native_display_(0),
|
||||||
native_window_(0) {
|
native_window_(0) {
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
|
||||||
|
|
||||||
window_ = SDL_CreateWindow("anbox",
|
window_ = SDL_CreateWindow("anbox", x, y, width, height, SDL_WINDOW_OPENGL);
|
||||||
SDL_WINDOWPOS_UNDEFINED,
|
|
||||||
SDL_WINDOWPOS_UNDEFINED,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
SDL_WINDOW_OPENGL);
|
|
||||||
if (!window_) {
|
if (!window_) {
|
||||||
const auto message = utils::string_format("Failed to create window: %s", SDL_GetError());
|
const auto message = utils::string_format("Failed to create window: %s", SDL_GetError());
|
||||||
BOOST_THROW_EXCEPTION(std::runtime_error(message));
|
BOOST_THROW_EXCEPTION(std::runtime_error(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SDL_SysWMinfo info;
|
SDL_SysWMinfo info;
|
||||||
SDL_VERSION(&info.version);
|
SDL_VERSION(&info.version);
|
||||||
SDL_GetWindowWMInfo(window_, &info);
|
SDL_GetWindowWMInfo(window_, &info);
|
||||||
|
|
@ -363,132 +51,15 @@ Window::Window(const std::shared_ptr<input::Manager> &input_manager,
|
||||||
}
|
}
|
||||||
|
|
||||||
int actual_width = 0, actual_height = 0;
|
int actual_width = 0, actual_height = 0;
|
||||||
|
int actual_x = 0, actual_y = 0;
|
||||||
SDL_GetWindowSize(window_, &actual_width, &actual_height);
|
SDL_GetWindowSize(window_, &actual_width, &actual_height);
|
||||||
|
SDL_GetWindowPosition(window_, &actual_x, &actual_y);
|
||||||
DEBUG("Window created with %d x %d", actual_width, actual_height);
|
DEBUG("Window created {%d,%d,%d,%d}", actual_x, actual_y, actual_width, actual_height);
|
||||||
|
|
||||||
// Create our touch panel input device
|
|
||||||
touchpanel_ = input_manager->create_device();
|
|
||||||
touchpanel_->set_name("anbox-touchpanel");
|
|
||||||
touchpanel_->set_driver_version(1);
|
|
||||||
touchpanel_->set_input_id({ BUS_VIRTUAL, 1, 1, 1 });
|
|
||||||
touchpanel_->set_physical_location("none");
|
|
||||||
touchpanel_->set_abs_bit(ABS_MT_TRACKING_ID);
|
|
||||||
touchpanel_->set_abs_bit(ABS_MT_SLOT);
|
|
||||||
touchpanel_->set_abs_bit(ABS_MT_POSITION_X);
|
|
||||||
touchpanel_->set_abs_bit(ABS_MT_POSITION_Y);
|
|
||||||
touchpanel_->set_prop_bit(INPUT_PROP_DIRECT);
|
|
||||||
touchpanel_->set_abs_min(ABS_MT_POSITION_X, 0);
|
|
||||||
touchpanel_->set_abs_max(ABS_MT_POSITION_X, static_cast<std::uint32_t>(actual_width));
|
|
||||||
touchpanel_->set_abs_min(ABS_MT_POSITION_Y, 0);
|
|
||||||
touchpanel_->set_abs_max(ABS_MT_POSITION_Y, static_cast<std::uint32_t>(actual_height));
|
|
||||||
touchpanel_->set_abs_max(ABS_MT_SLOT, 10);
|
|
||||||
touchpanel_->set_abs_max(ABS_MT_TRACKING_ID, 255);
|
|
||||||
|
|
||||||
pointer_ = input_manager->create_device();
|
|
||||||
pointer_->set_name("anbox-pointer");
|
|
||||||
pointer_->set_driver_version(1);
|
|
||||||
pointer_->set_input_id({ BUS_VIRTUAL, 2, 2, 2 });
|
|
||||||
pointer_->set_physical_location("none");
|
|
||||||
pointer_->set_key_bit(BTN_MOUSE);
|
|
||||||
// NOTE: We don't use REL_X/REL_Y in reality but have to specify them here
|
|
||||||
// to allow InputFlinger to detect we're a cursor device.
|
|
||||||
pointer_->set_rel_bit(REL_X);
|
|
||||||
pointer_->set_rel_bit(REL_Y);
|
|
||||||
pointer_->set_rel_bit(REL_HWHEEL);
|
|
||||||
pointer_->set_rel_bit(REL_WHEEL);
|
|
||||||
pointer_->set_prop_bit(INPUT_PROP_POINTER);
|
|
||||||
|
|
||||||
keyboard_ = input_manager->create_device();
|
|
||||||
keyboard_->set_name("anbox-keyboard");
|
|
||||||
keyboard_->set_driver_version(1);
|
|
||||||
keyboard_->set_input_id({ BUS_VIRTUAL, 3, 3, 3 });
|
|
||||||
keyboard_->set_physical_location("none");
|
|
||||||
keyboard_->set_key_bit(BTN_MISC);
|
|
||||||
keyboard_->set_key_bit(KEY_OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::~Window() {
|
Window::~Window() {
|
||||||
}
|
if (window_)
|
||||||
|
SDL_DestroyWindow(window_);
|
||||||
void Window::process_input_event(const SDL_Event &event) {
|
|
||||||
static SlotFingerMapper mapper;
|
|
||||||
std::vector<input::Event> touch_events;
|
|
||||||
std::vector<input::Event> mouse_events;
|
|
||||||
std::vector<input::Event> keyboard_events;
|
|
||||||
|
|
||||||
const auto id = event.tfinger.fingerId;
|
|
||||||
const auto slot = mapper.find_or_create(id);
|
|
||||||
|
|
||||||
switch (event.type) {
|
|
||||||
case SDL_FINGERUP:
|
|
||||||
touch_events.push_back({ EV_ABS, ABS_MT_SLOT, slot });
|
|
||||||
touch_events.push_back({ EV_ABS, ABS_MT_TRACKING_ID, -1 });
|
|
||||||
touch_events.push_back({ EV_KEY, BTN_TOUCH, 0 });
|
|
||||||
touch_events.push_back({ EV_KEY, BTN_TOOL_FINGER, 0 });
|
|
||||||
touch_events.push_back({ EV_SYN, SYN_REPORT, 0 });
|
|
||||||
mapper.erase(id);
|
|
||||||
break;
|
|
||||||
case SDL_FINGERDOWN:
|
|
||||||
touch_events.push_back({ EV_ABS, ABS_MT_SLOT, slot });
|
|
||||||
touch_events.push_back({ EV_ABS, ABS_MT_TRACKING_ID, static_cast<std::int32_t>(id) });
|
|
||||||
touch_events.push_back({ EV_ABS, ABS_MT_POSITION_X, static_cast<std::int32_t>(event.tfinger.x) });
|
|
||||||
touch_events.push_back({ EV_ABS, ABS_MT_POSITION_Y, static_cast<std::int32_t>(event.tfinger.y) });
|
|
||||||
touch_events.push_back({ EV_SYN, SYN_REPORT, 0 });
|
|
||||||
break;
|
|
||||||
case SDL_FINGERMOTION:
|
|
||||||
touch_events.push_back({ EV_ABS, ABS_MT_SLOT, slot });
|
|
||||||
touch_events.push_back({ EV_ABS, ABS_MT_TRACKING_ID, static_cast<std::int32_t>(id) });
|
|
||||||
touch_events.push_back({ EV_KEY, BTN_TOUCH, 1 });
|
|
||||||
touch_events.push_back({ EV_KEY, BTN_TOOL_FINGER, 1 });
|
|
||||||
touch_events.push_back({ EV_ABS, ABS_MT_POSITION_X, static_cast<std::int32_t>(event.tfinger.x) });
|
|
||||||
touch_events.push_back({ EV_ABS, ABS_MT_POSITION_Y, static_cast<std::int32_t>(event.tfinger.y) });
|
|
||||||
touch_events.push_back({ EV_SYN, SYN_REPORT, 0 });
|
|
||||||
break;
|
|
||||||
case SDL_MOUSEBUTTONDOWN:
|
|
||||||
mouse_events.push_back({ EV_KEY, BTN_LEFT, 1 });
|
|
||||||
mouse_events.push_back({ EV_SYN, SYN_REPORT, 0 });
|
|
||||||
break;
|
|
||||||
case SDL_MOUSEBUTTONUP:
|
|
||||||
mouse_events.push_back({ EV_KEY, BTN_LEFT, 0 });
|
|
||||||
mouse_events.push_back({ EV_SYN, SYN_REPORT, 0 });
|
|
||||||
break;
|
|
||||||
case SDL_MOUSEMOTION:
|
|
||||||
// NOTE: Sending relative move events doesn't really work and we have changes
|
|
||||||
// in libinputflinger to take ABS_X/ABS_Y instead for absolute position events.
|
|
||||||
mouse_events.push_back({ EV_ABS, ABS_X, static_cast<std::int32_t>(event.motion.x) });
|
|
||||||
mouse_events.push_back({ EV_ABS, ABS_Y, static_cast<std::int32_t>(event.motion.y) });
|
|
||||||
mouse_events.push_back({ EV_SYN, SYN_REPORT, 0 });
|
|
||||||
break;
|
|
||||||
case SDL_MOUSEWHEEL:
|
|
||||||
mouse_events.push_back({ EV_REL, REL_WHEEL, static_cast<std::int32_t>(event.wheel.y) });
|
|
||||||
break;
|
|
||||||
case SDL_KEYDOWN: {
|
|
||||||
const auto code = convert_sdl_scancode_to_evdev(event.key.keysym.scancode);
|
|
||||||
if (code == KEY_RESERVED)
|
|
||||||
break;
|
|
||||||
keyboard_events.push_back({ EV_KEY, code, 1 });
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SDL_KEYUP: {
|
|
||||||
const auto code = convert_sdl_scancode_to_evdev(event.key.keysym.scancode);
|
|
||||||
if (code == KEY_RESERVED)
|
|
||||||
break;
|
|
||||||
keyboard_events.push_back({ EV_KEY, code, 0 });
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (touch_events.size() > 0)
|
|
||||||
touchpanel_->send_events(touch_events);
|
|
||||||
|
|
||||||
if (mouse_events.size() > 0)
|
|
||||||
pointer_->send_events(mouse_events);
|
|
||||||
|
|
||||||
if (keyboard_events.size() > 0)
|
|
||||||
keyboard_->send_events(keyboard_events);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLNativeWindowType Window::native_window() const {
|
EGLNativeWindowType Window::native_window() const {
|
||||||
|
|
|
||||||
|
|
@ -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 @@
|
||||||
|
|
||||||
#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
|
||||||
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() {
|
||||||
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() {
|
||||||
|
|
||||||
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 @@
|
||||||
#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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue