Migrate emugl layer into the core
This commit is contained in:
parent
1e168fd4aa
commit
609d80395c
53 changed files with 51 additions and 901 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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})
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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, ¶meters);
|
||||
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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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}});
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
//
|
||||
Loading…
Add table
Add a link
Reference in a new issue