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(GLESv1_dec)
|
||||||
add_subdirectory(GLESv2_dec)
|
add_subdirectory(GLESv2_dec)
|
||||||
add_subdirectory(libOpenGLESDispatch)
|
add_subdirectory(libOpenGLESDispatch)
|
||||||
add_subdirectory(libOpenglRender)
|
|
||||||
add_subdirectory(renderControl_dec)
|
add_subdirectory(renderControl_dec)
|
||||||
add_subdirectory(Translator)
|
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}
|
||||||
${CMAKE_SOURCE_DIR}/src
|
${CMAKE_SOURCE_DIR}/src
|
||||||
${CMAKE_SOURCE_DIR}/external/process-cpp-minimal/include
|
${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/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(
|
protobuf_generate_cpp(
|
||||||
|
|
@ -97,6 +107,29 @@ set(SOURCES
|
||||||
anbox/graphics/density.h
|
anbox/graphics/density.h
|
||||||
anbox/graphics/rect.cpp
|
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/display.cpp
|
||||||
anbox/wm/task.cpp
|
anbox/wm/task.cpp
|
||||||
anbox/wm/manager.cpp
|
anbox/wm/manager.cpp
|
||||||
|
|
@ -150,7 +183,12 @@ target_link_libraries(anbox-core
|
||||||
${LXC_LIBRARIES}
|
${LXC_LIBRARIES}
|
||||||
pthread
|
pthread
|
||||||
process-cpp
|
process-cpp
|
||||||
OpenglRender
|
emugl_common
|
||||||
|
GLESv1_dec
|
||||||
|
GLESv2_dec
|
||||||
|
renderControl_dec
|
||||||
|
OpenGLESDispatch
|
||||||
|
OpenglCodecCommon
|
||||||
anbox-protobuf)
|
anbox-protobuf)
|
||||||
|
|
||||||
add_executable(anbox main.cpp)
|
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.settings/com.android.settings.FallbackHome",
|
||||||
"com.android.systemui.ImageWallpaper",
|
"com.android.systemui.ImageWallpaper",
|
||||||
"InputMethod",
|
"InputMethod",
|
||||||
|
"com.android.quicksearchbox/com.android.quicksearchbox.SearchActivity",
|
||||||
};
|
};
|
||||||
return std::find(blacklist.begin(), blacklist.end(), name) != blacklist.end();
|
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;
|
auto height = layer.display_frame.bottom - layer.display_frame.top;
|
||||||
|
|
||||||
if (!window) {
|
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,
|
window = FrameBuffer::getFB()->createWindow(layer.display_frame.left,
|
||||||
layer.display_frame.top,
|
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());
|
printf("Failed to create window for layer '%s'\n", layer.name.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
layers_.insert({ layer.name, Layer{window, true}});
|
layers_.insert({ layer.name, Layer{window, true}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,25 +59,6 @@ intptr_t RenderThread::main() {
|
||||||
|
|
||||||
ReadBuffer readBuf(STREAM_BUFFER_SIZE);
|
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) {
|
while (1) {
|
||||||
|
|
||||||
int stat = readBuf.getData(m_stream);
|
int stat = readBuf.getData(m_stream);
|
||||||
|
|
@ -85,29 +66,6 @@ intptr_t RenderThread::main() {
|
||||||
break;
|
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;
|
bool progress;
|
||||||
do {
|
do {
|
||||||
progress = false;
|
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
|
// Release references to the current thread's context/surfaces if any
|
||||||
//
|
//
|
||||||
Loading…
Add table
Add a link
Reference in a new issue