Migrate emugl layer into the core

This commit is contained in:
Simon Fels 2016-11-15 13:59:53 +01:00
commit 609d80395c
53 changed files with 51 additions and 901 deletions

View file

@ -1,6 +1,5 @@
add_subdirectory(GLESv1_dec)
add_subdirectory(GLESv2_dec)
add_subdirectory(libOpenGLESDispatch)
add_subdirectory(libOpenglRender)
add_subdirectory(renderControl_dec)
add_subdirectory(Translator)

View file

@ -1,34 +0,0 @@
set(SOURCES
ColorBuffer.cpp
DisplayManager.cpp
FbConfig.cpp
FrameBuffer.cpp
LayerManager.cpp
NativeSubWindow.h
NativeSubWindow_delegate.cpp
ReadBuffer.cpp
RenderContext.cpp
RenderControl.cpp
RenderServer.cpp
RenderThread.cpp
RenderThreadInfo.cpp
RenderApi.cpp
RenderWindow.cpp
SocketStream.cpp
TcpStream.cpp
TextureDraw.cpp
TextureResize.cpp
TimeUtils.cpp
UnixStream.cpp
WindowSurface.cpp)
add_library(OpenglRender ${SOURCES})
target_link_libraries(OpenglRender
emugl_common
GLESv1_dec
GLESv2_dec
renderControl_dec
OpenGLESDispatch
OpenglCodecCommon
${EGL_LDFLAGS}
${EGL_LIBRARIES})

View file

@ -1,101 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "NativeSubWindow.h"
#include <Cocoa/Cocoa.h>
/*
* EmuGLView inherit from NSView and override the isOpaque
* method to return YES. That prevents drawing of underlying window/view
* when the view needs to be redrawn.
*/
@interface EmuGLView : NSView {
} @end
@implementation EmuGLView
- (BOOL)isOpaque {
return YES;
}
@end
EGLNativeWindowType createSubWindow(FBNativeWindowType p_window,
int x,
int y,
int width,
int height,
SubWindowRepaintCallback repaint_callback,
void* repaint_callback_param) {
NSWindow* win = (NSWindow *)p_window;
if (!win) {
return NULL;
}
/* (x,y) assume an upper-left origin, but Cocoa uses a lower-left origin */
NSRect content_rect = [win contentRectForFrameRect:[win frame]];
int cocoa_y = (int)content_rect.size.height - (y + height);
NSRect contentRect = NSMakeRect(x, cocoa_y, width, height);
NSView *glView = [[EmuGLView alloc] initWithFrame:contentRect];
if (glView) {
[glView setWantsBestResolutionOpenGLSurface:YES];
[[win contentView] addSubview:glView];
[win makeKeyAndOrderFront:nil];
}
return (EGLNativeWindowType)glView;
}
void destroySubWindow(EGLNativeWindowType win) {
if(win){
NSView *glView = (NSView *)win;
[glView removeFromSuperview];
[glView release];
}
}
int moveSubWindow(FBNativeWindowType p_parent_window,
EGLNativeWindowType p_sub_window,
int x,
int y,
int width,
int height) {
NSWindow *win = (NSWindow *)p_parent_window;
if (!win) {
return 0;
}
NSView *glView = (NSView *)p_sub_window;
if (!glView) {
return 0;
}
/* The view must be removed from the hierarchy to be properly resized */
[glView removeFromSuperview];
/* (x,y) assume an upper-left origin, but Cocoa uses a lower-left origin */
NSRect content_rect = [win contentRectForFrameRect:[win frame]];
int cocoa_y = (int)content_rect.size.height - (y + height);
NSRect newFrame = NSMakeRect(x, cocoa_y, width, height);
[glView setFrame:newFrame];
/* Re-add the sub-window to the view hierarchy */
[[win contentView] addSubview:glView];
[win makeKeyAndOrderFront:nil];
return 1;
}

View file

@ -1,201 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define MIR_EGL_PLATFORM
#include "mir_support/shared_state.h"
#include "NativeSubWindow.h"
#include "OpenglCodecCommon/ErrorLog.h"
#include <stdexcept>
#include <string>
#include <map>
#include <mirclient/mir_toolkit/mir_client_library.h>
namespace {
std::map<EGLNativeWindowType,MirSurface*> surfaces;
static const MirDisplayOutput *find_active_output(
const MirDisplayConfiguration *conf)
{
const MirDisplayOutput *output = NULL;
int d;
for (d = 0; d < (int)conf->num_outputs; d++)
{
const MirDisplayOutput *out = conf->outputs + d;
if (out->used &&
out->connected &&
out->num_modes &&
out->current_mode < out->num_modes)
{
output = out;
break;
}
}
return output;
}
}
MirPixelFormat defaultPixelFormatFor(MirConnection *connection)
{
MirPixelFormat format;
unsigned int nformats;
mir_connection_get_available_surface_formats(connection, &format, 1, &nformats);
return format;
}
void handleSurfaceEvent(const MirSurfaceEvent *event) {
MirSurfaceAttrib attrib = mir_surface_event_get_attribute(event);
if (attrib != mir_surface_attrib_visibility)
return;
switch (mir_surface_event_get_attribute(event)) {
case mir_surface_visibility_exposed:
ERR("Surface exposed\n");
break;
case mir_surface_visibility_occluded:
ERR("Surface occluded\n");
break;
default:
break;
}
}
void surfaceEventHandler(MirSurface *surface, MirEvent const *event, void *context) {
switch (mir_event_get_type(event)) {
case mir_event_type_input:
break;
case mir_event_type_surface:
handleSurfaceEvent(mir_event_get_surface_event(event));
break;
case mir_event_type_resize:
{
MirResizeEvent const *resize_event = mir_event_get_resize_event(event);
ERR("Resized to %dx%d\n",
mir_resize_event_get_width(resize_event),
mir_resize_event_get_height(resize_event));
}
break;
case mir_event_type_close_surface:
break;
case mir_event_type_surface_output:
{
MirSurfaceOutputEvent const *output_event = mir_event_get_surface_output_event(event);
ERR("dpi %i output id %d\n",
mir_surface_output_event_get_dpi(output_event),
mir_surface_output_event_get_output_id(output_event));
}
break;
default:
break;
}
}
EGLNativeWindowType createSubWindow(FBNativeWindowType p_window,
int x,
int y,
int width,
int height,
SubWindowRepaintCallback repaint_callback,
void* repaint_callback_param) {
(void) p_window;
(void) x;
(void) y;
(void) width;
(void) height;
(void) repaint_callback;
(void) repaint_callback_param;
mir::support::SharedState::get()->ensure_connection();
const auto pixel_format = defaultPixelFormatFor(mir::support::SharedState::get()->connection());
ERR("Selected pixel format %d\n", pixel_format);
MirDisplayConfiguration* display_config =
mir_connection_create_display_config(mir::support::SharedState::get()->connection());
const MirDisplayOutput *output = find_active_output(display_config);
if (!output)
throw new std::runtime_error("Failed to find active output display");
const MirDisplayMode *mode = &output->modes[output->current_mode];
auto spec = mir_connection_create_spec_for_normal_surface(
mir::support::SharedState::get()->connection(),
mode->vertical_resolution,
mode->horizontal_resolution,
pixel_format);
mir_surface_spec_set_name(spec, "anbox");
mir_surface_spec_set_event_handler(spec, surfaceEventHandler, nullptr);
ERR("Selecting output id %d", output->output_id);
mir_surface_spec_set_fullscreen_on_output(spec, output->output_id);
mir_surface_spec_set_buffer_usage(spec, mir_buffer_usage_hardware);
mir_display_config_destroy(display_config);
auto surface = mir_surface_create_sync(spec);
mir_surface_spec_release(spec);
if (!mir_surface_is_valid(surface)) {
ERR("surface error: %s\n", mir_surface_get_error_message(surface));
throw std::runtime_error("Failed to create a Mir surface");
}
MirSurfaceParameters parameters;
mir_surface_get_parameters(surface, &parameters);
ERR("width %i height %i output id %i\n",
parameters.width,
parameters.height,
parameters.output_id);
auto surface_buffer_stream = mir_surface_get_buffer_stream(surface);
auto native_window = reinterpret_cast<EGLNativeWindowType>(
mir_buffer_stream_get_egl_native_window(surface_buffer_stream));
surfaces.insert({ native_window, surface });
return native_window;
}
void destroySubWindow(EGLNativeWindowType win) {
if (surfaces.find(win) == surfaces.end())
return;
auto surface = surfaces[win];
surfaces.erase(win);
mir_surface_release_sync(surface);
}
int moveSubWindow(FBNativeWindowType p_parent_window,
EGLNativeWindowType p_sub_window,
int x,
int y,
int width,
int height) {
ERR("%s: Not implemented", __func__);
return true;
}

View file

@ -1,39 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "NativeSubWindow.h"
EGLNativeWindowType createSubWindow(FBNativeWindowType p_window,
int x,
int y,
int width,
int height,
SubWindowRepaintCallback repaint_callback,
void* repaint_callback_param) {
return NULL;
}
void destroySubWindow(EGLNativeWindowType win) {
}
int moveSubWindow(FBNativeWindowType p_parent_window,
EGLNativeWindowType p_sub_window,
int x,
int y,
int width,
int height) {
return false;
}

View file

@ -1,90 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "NativeSubWindow.h"
struct SubWindowUserData {
SubWindowRepaintCallback repaint_callback;
void* repaint_callback_param;
};
static LRESULT CALLBACK subWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
if (uMsg == WM_PAINT) {
auto user_data =
(SubWindowUserData*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
if (user_data && user_data->repaint_callback) {
user_data->repaint_callback(user_data->repaint_callback_param);
}
} else if (uMsg == WM_NCDESTROY) {
SubWindowUserData* user_data =
(SubWindowUserData*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
delete user_data;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
EGLNativeWindowType createSubWindow(FBNativeWindowType p_window,
int x, int y,int width, int height,
SubWindowRepaintCallback repaint_callback,
void* repaint_callback_param){
static const char className[] = "subWin";
WNDCLASS wc = {};
if (!GetClassInfo(GetModuleHandle(NULL), className, &wc)) {
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;// redraw if size changes
wc.lpfnWndProc = &subWindowProc; // points to window procedure
wc.cbWndExtra = sizeof(void*) ; // save extra window memory
wc.lpszClassName = className; // name of window class
RegisterClass(&wc);
}
EGLNativeWindowType ret = CreateWindowEx(
WS_EX_NOPARENTNOTIFY, // do not bother our parent window
className,
"sub",
WS_CHILD|WS_DISABLED,
x,y,width,height,
p_window,
NULL,
NULL,
NULL);
auto user_data = new SubWindowUserData();
user_data->repaint_callback = repaint_callback;
user_data->repaint_callback_param = repaint_callback_param;
SetWindowLongPtr(ret, GWLP_USERDATA, (LONG_PTR)user_data);
ShowWindow(ret, SW_SHOW);
return ret;
}
void destroySubWindow(EGLNativeWindowType win){
PostMessage(win, WM_CLOSE, 0, 0);
}
int moveSubWindow(FBNativeWindowType p_parent_window,
EGLNativeWindowType p_sub_window,
int x,
int y,
int width,
int height) {
BOOL ret = MoveWindow(p_sub_window,
x,
y,
width,
height,
TRUE);
return ret;
}

View file

@ -1,105 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "NativeSubWindow.h"
#include <stdio.h>
static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg) {
if (e->type == MapNotify && e->xmap.window == (Window)arg) {
return 1;
}
return 0;
}
static Bool WaitForConfigureNotify(Display *d, XEvent *e, char *arg) {
if (e->type == ConfigureNotify && e->xmap.window == (Window)arg) {
return 1;
}
return 0;
}
static Display *s_display = NULL;
EGLNativeWindowType createSubWindow(FBNativeWindowType p_window,
int x,
int y,
int width,
int height,
SubWindowRepaintCallback repaint_callback,
void* repaint_callback_param) {
// The call to this function is protected by a lock
// in FrameBuffer so it is safe to check and initialize s_display here
if (!s_display) {
s_display = XOpenDisplay(NULL);
}
XSetWindowAttributes wa;
wa.event_mask = StructureNotifyMask;
wa.override_redirect = True;
Window win = XCreateWindow(s_display,
p_window,
x,
y,
width,
height,
0,
CopyFromParent,
CopyFromParent,
CopyFromParent,
CWEventMask,
&wa);
XMapWindow(s_display,win);
XSetWindowBackground(s_display, win, BlackPixel(s_display, 0));
XEvent e;
XIfEvent(s_display, &e, WaitForMapNotify, (char *)win);
return win;
}
void destroySubWindow(EGLNativeWindowType win) {
if (!s_display) {
return;
}
XDestroyWindow(s_display, win);
}
int moveSubWindow(FBNativeWindowType p_parent_window,
EGLNativeWindowType p_sub_window,
int x,
int y,
int width,
int height) {
// This value is set during create, so if it is still null, simply
// return because the global state is corrupted
if (!s_display) {
return false;
}
// This prevents flicker on resize.
XSetWindowBackgroundPixmap(s_display, p_sub_window, None);
int ret = XMoveResizeWindow(
s_display,
p_sub_window,
x,
y,
width,
height);
XEvent e;
XIfEvent(s_display, &e, WaitForConfigureNotify, (char *)p_sub_window);
return ret;
}

View file

@ -1,241 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Win32PipeStream.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <windows.h>
#ifndef _WIN32
#error ONLY BUILD THIS SOURCE FILE FOR WINDOWS!
#endif
/* The official documentation states that the name of a given named
* pipe cannot be more than 256 characters long.
*/
#define NAMED_PIPE_MAX 256
Win32PipeStream::Win32PipeStream(size_t bufSize) :
SocketStream(bufSize),
m_pipe(INVALID_HANDLE_VALUE)
{
}
Win32PipeStream::Win32PipeStream(HANDLE pipe, size_t bufSize) :
SocketStream(-1, bufSize),
m_pipe(pipe)
{
}
Win32PipeStream::~Win32PipeStream()
{
if (m_pipe != INVALID_HANDLE_VALUE) {
CloseHandle(m_pipe);
m_pipe = INVALID_HANDLE_VALUE;
}
}
/* Initialize the pipe name corresponding to a given port
*/
static void
make_pipe_name(char *path, size_t pathlen, int port_number)
{
snprintf(path, pathlen, "\\\\.\\pipe\\qemu-gles-%d", port_number);
}
/* Technical note: Named pipes work differently from BSD Sockets.
* One does not create/bind a pipe, and collect a new handle each
* time a client connects with accept().
*
* Instead, the server creates a new pipe instance each time it wants
* to get a new client connection, then calls ConnectNamedPipe() to
* wait for a connection.
*
* So listen() is a no-op, and accept() really creates the pipe handle.
*
* Also, connect() must create a pipe handle with CreateFile() and
* wait for a server instance with WaitNamedPipe()
*/
int Win32PipeStream::listen(char addrstr[MAX_ADDRSTR_LEN])
{
m_port = GetCurrentProcessId();
make_pipe_name(addrstr, MAX_ADDRSTR_LEN, m_port);
return 0;
}
SocketStream * Win32PipeStream::accept()
{
char path[NAMED_PIPE_MAX+1];
SocketStream* clientStream;
HANDLE pipe;
make_pipe_name(path, sizeof(path), m_port);
pipe = ::CreateNamedPipe(
path, // pipe name
PIPE_ACCESS_DUPLEX, // read-write access
PIPE_TYPE_BYTE | // byte-oriented writes
PIPE_READMODE_BYTE | // byte-oriented reads
PIPE_WAIT, // blocking operations
PIPE_UNLIMITED_INSTANCES, // no limit on clients
4096, // input buffer size
4096, // output buffer size
0, // client time-out
NULL); // default security attributes
if (pipe == INVALID_HANDLE_VALUE) {
ERR("%s: CreateNamedPipe failed %d\n", __FUNCTION__, (int)GetLastError());
return NULL;
}
// Stupid Win32 API design: If a client is already connected, then
// ConnectNamedPipe will return 0, and GetLastError() will return
// ERROR_PIPE_CONNECTED. This is not an error! It just means that the
// function didn't have to wait.
//
if (::ConnectNamedPipe(pipe, NULL) == 0 && GetLastError() != ERROR_PIPE_CONNECTED) {
ERR("%s: ConnectNamedPipe failed: %d\n", __FUNCTION__, (int)GetLastError());
CloseHandle(pipe);
return NULL;
}
clientStream = new Win32PipeStream(pipe, m_bufsize);
return clientStream;
}
int Win32PipeStream::connect(const char* addr)
{
HANDLE pipe;
int tries = 10;
/* We're going to loop in order to wait for the pipe server to
* be setup properly.
*/
for (; tries > 0; tries--) {
pipe = ::CreateFile(
addr, // pipe name
GENERIC_READ | GENERIC_WRITE, // read & write
0, // no sharing
NULL, // default security attrs
OPEN_EXISTING, // open existing pipe
0, // default attributes
NULL); // no template file
/* If we have a valid pipe handle, break from the loop */
if (pipe != INVALID_HANDLE_VALUE) {
break;
}
/* We can get here if the pipe is busy, i.e. if the server hasn't
* create a new pipe instance to service our request. In which case
* GetLastError() will return ERROR_PIPE_BUSY.
*
* If so, then use WaitNamedPipe() to wait for a decent time
* to try again.
*/
if (GetLastError() != ERROR_PIPE_BUSY) {
/* Not ERROR_PIPE_BUSY */
ERR("%s: CreateFile failed: %d\n", __FUNCTION__, (int)GetLastError());
errno = EINVAL;
return -1;
}
/* Wait for 5 seconds */
if ( !WaitNamedPipe(addr, 5000) ) {
ERR("%s: WaitNamedPipe failed: %d\n", __FUNCTION__, (int)GetLastError());
errno = EINVAL;
return -1;
}
}
m_pipe = pipe;
return 0;
}
/* Special buffer methods, since we can't use socket functions here */
int Win32PipeStream::commitBuffer(size_t size)
{
if (m_pipe == INVALID_HANDLE_VALUE)
return -1;
size_t res = size;
int retval = 0;
while (res > 0) {
DWORD written;
if (! ::WriteFile(m_pipe, (const char *)m_buf + (size - res), res, &written, NULL)) {
retval = -1;
ERR("%s: failed: %d\n", __FUNCTION__, (int)GetLastError());
break;
}
res -= written;
}
return retval;
}
const unsigned char *Win32PipeStream::readFully(void *buf, size_t len)
{
if (m_pipe == INVALID_HANDLE_VALUE)
return NULL;
if (!buf) {
return NULL; // do not allow NULL buf in that implementation
}
size_t res = len;
while (res > 0) {
DWORD readcount = 0;
if (! ::ReadFile(m_pipe, (char *)buf + (len - res), res, &readcount, NULL) || readcount == 0) {
errno = (int)GetLastError();
return NULL;
}
res -= readcount;
}
return (const unsigned char *)buf;
}
const unsigned char *Win32PipeStream::read( void *buf, size_t *inout_len)
{
size_t len = *inout_len;
DWORD readcount;
if (m_pipe == INVALID_HANDLE_VALUE)
return NULL;
if (!buf) {
return NULL; // do not allow NULL buf in that implementation
}
if (!::ReadFile(m_pipe, (char *)buf, len, &readcount, NULL)) {
errno = (int)GetLastError();
return NULL;
}
*inout_len = (size_t)readcount;
return (const unsigned char *)buf;
}
void Win32PipeStream::forceStop()
{
HANDLE handle = m_pipe;
m_pipe = INVALID_HANDLE_VALUE;
CloseHandle(handle);
}

View file

@ -1,42 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __WIN32_PIPE_STREAM_H
#define __WIN32_PIPE_STREAM_H
#include "SocketStream.h"
#include <windows.h>
class Win32PipeStream : public SocketStream {
public:
explicit Win32PipeStream(size_t bufsize = 10000);
virtual ~Win32PipeStream();
virtual int listen(char addrstr[MAX_ADDRSTR_LEN]);
virtual SocketStream *accept();
virtual int connect(const char* addr);
virtual int commitBuffer(size_t size);
virtual const unsigned char *readFully(void *buf, size_t len);
virtual const unsigned char *read(void *buf, size_t *inout_len);
virtual void forceStop();
private:
Win32PipeStream(HANDLE pipe, size_t bufSize);
HANDLE m_pipe;
int m_port;
};
#endif

View file

@ -12,7 +12,17 @@ include_directories(
${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/src
${CMAKE_SOURCE_DIR}/external/process-cpp-minimal/include
${CMAKE_SOURCE_DIR}/external/android-emugl/shared
${CMAKE_SOURCE_DIR}/external/android-emugl/host/include
${CMAKE_SOURCE_DIR}/external/android-emugl/shared/OpenglCodecCommon
${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs
${CMAKE_SOURCE_DIR}/external/android-emugl/host/include/libOpenglRender
${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs/GLESv1_dec
${CMAKE_BINARY_DIR}/external/android-emugl/host/libs/GLESv1_dec
${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs/GLESv2_dec
${CMAKE_BINARY_DIR}/external/android-emugl/host/libs/GLESv2_dec
${CMAKE_SOURCE_DIR}/external/android-emugl/host/libs/renderControl_dec
${CMAKE_BINARY_DIR}/external/android-emugl/host/libs/renderControl_dec
)
protobuf_generate_cpp(
@ -97,6 +107,29 @@ set(SOURCES
anbox/graphics/density.h
anbox/graphics/rect.cpp
anbox/graphics/emugl/ColorBuffer.cpp
anbox/graphics/emugl/DisplayManager.cpp
anbox/graphics/emugl/FbConfig.cpp
anbox/graphics/emugl/FrameBuffer.cpp
anbox/graphics/emugl/LayerManager.cpp
anbox/graphics/emugl/NativeSubWindow_delegate.cpp
anbox/graphics/emugl/NativeSubWindow.h
anbox/graphics/emugl/ReadBuffer.cpp
anbox/graphics/emugl/RenderApi.cpp
anbox/graphics/emugl/RenderContext.cpp
anbox/graphics/emugl/RenderControl.cpp
anbox/graphics/emugl/RenderServer.cpp
anbox/graphics/emugl/RenderThread.cpp
anbox/graphics/emugl/RenderThreadInfo.cpp
anbox/graphics/emugl/RenderWindow.cpp
anbox/graphics/emugl/SocketStream.cpp
anbox/graphics/emugl/TcpStream.cpp
anbox/graphics/emugl/TextureDraw.cpp
anbox/graphics/emugl/TextureResize.cpp
anbox/graphics/emugl/TimeUtils.cpp
anbox/graphics/emugl/UnixStream.cpp
anbox/graphics/emugl/WindowSurface.cpp
anbox/wm/display.cpp
anbox/wm/task.cpp
anbox/wm/manager.cpp
@ -150,7 +183,12 @@ target_link_libraries(anbox-core
${LXC_LIBRARIES}
pthread
process-cpp
OpenglRender
emugl_common
GLESv1_dec
GLESv2_dec
renderControl_dec
OpenGLESDispatch
OpenglCodecCommon
anbox-protobuf)
add_executable(anbox main.cpp)

View file

@ -38,6 +38,7 @@ bool is_layer_blacklisted(const std::string &name) {
"com.android.settings/com.android.settings.FallbackHome",
"com.android.systemui.ImageWallpaper",
"InputMethod",
"com.android.quicksearchbox/com.android.quicksearchbox.SearchActivity",
};
return std::find(blacklist.begin(), blacklist.end(), name) != blacklist.end();
}
@ -87,6 +88,16 @@ void LayerManager::post_layer(const LayerInfo &layer) {
auto height = layer.display_frame.bottom - layer.display_frame.top;
if (!window) {
printf("New layer '%s' display_frame={%d,%d,%d,%d} source_crop={%d,%d,%d,%d}\n",
layer.name.c_str(),
layer.display_frame.left,
layer.display_frame.top,
layer.display_frame.right,
layer.display_frame.bottom,
layer.source_crop.left,
layer.source_crop.top,
layer.source_crop.right,
layer.source_crop.bottom);
window = FrameBuffer::getFB()->createWindow(layer.display_frame.left,
layer.display_frame.top,
@ -95,6 +106,7 @@ void LayerManager::post_layer(const LayerInfo &layer) {
printf("Failed to create window for layer '%s'\n", layer.name.c_str());
return;
}
layers_.insert({ layer.name, Layer{window, true}});
}

View file

@ -59,25 +59,6 @@ intptr_t RenderThread::main() {
ReadBuffer readBuf(STREAM_BUFFER_SIZE);
int stats_totalBytes = 0;
long long stats_t0 = GetCurrentTimeMS();
//
// open dump file if RENDER_DUMP_DIR is defined
//
const char *dump_dir = getenv("RENDERER_DUMP_DIR");
FILE *dumpFP = NULL;
if (dump_dir) {
size_t bsize = strlen(dump_dir) + 32;
char *fname = new char[bsize];
snprintf(fname,bsize,"%s/stream_%p", dump_dir, this);
dumpFP = fopen(fname, "wb");
if (!dumpFP) {
fprintf(stderr,"Warning: stream dump failed to open file %s\n",fname);
}
delete [] fname;
}
while (1) {
int stat = readBuf.getData(m_stream);
@ -85,29 +66,6 @@ intptr_t RenderThread::main() {
break;
}
#if 0
//
// log received bandwidth statistics
//
stats_totalBytes += readBuf.validData();
long long dt = GetCurrentTimeMS() - stats_t0;
if (dt > 1000) {
float dts = (float)dt / 1000.0f;
printf("Used Bandwidth %5.3f MB/s\n", ((float)stats_totalBytes / dts) / (1024.0f*1024.0f));
stats_totalBytes = 0;
stats_t0 = GetCurrentTimeMS();
}
#endif
//
// dump stream to file if needed
//
if (dumpFP) {
int skip = readBuf.validData() - stat;
fwrite(readBuf.buf()+skip, 1, readBuf.validData()-skip, dumpFP);
fflush(dumpFP);
}
bool progress;
do {
progress = false;
@ -147,10 +105,6 @@ intptr_t RenderThread::main() {
}
if (dumpFP) {
fclose(dumpFP);
}
//
// Release references to the current thread's context/surfaces if any
//