Skip to content

Clang 8.0 fixes, CMake, and Touch Screen working #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
out/
sdk/
.vscode
51 changes: 51 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
cmake_minimum_required(VERSION 3.11)

if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "MinSizeRel" CACHE STRING "Choose the type of build, options are: Debug, Release, or MinSizeRel." FORCE)
message(STATUS "CMAKE_BUILD_TYPE not set, defaulting to MinSizeRel.")
endif()

project(flutter LANGUAGES CXX)

message(STATUS "Generator .............. ${CMAKE_GENERATOR}")
message(STATUS "Build Type ............. ${CMAKE_BUILD_TYPE}")

include_directories(
${CMAKE_SYSROOT}/opt/vc/include
${CMAKE_SYSROOT}/opt/vc/include/interface/vcos/pthreads
${CMAKE_SYSROOT}/opt/vc/include/interface/vmcs_host/linux
${CMAKE_CURRENT_SOURCE_DIR}/../../../engine-prefix/src/engine/src/third_party/rapidjson/include
${CMAKE_CURRENT_SOURCE_DIR}/flutter/cpp_client_wrapper/include/flutter
${ENGINE_INCLUDE_DIR})

link_directories(
${CMAKE_SYSROOT}/opt/vc/lib
${ENGINE_LIBRARIES_DIR})

add_definitions(
-DSTANDALONE -D_LINUX -DTARGET_POSIX -D_REENTRANT
-D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
-DHAVE_LIBBCM_HOST -DUSE_EXTERNAL_LIBBCM_HOST
-fPIC -DPIC
-DUSE_RAPID_JSON
-DGLFW_INCLUDE_ES2
-DUSE_VCHIQ_ARM -DHAVE_LIBOPENMAX=2
-DUSE_EXTERNAL_OMX -DOMX -DOMX_SKIP64BIT)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -U_FORTIFY_SOURCE -Wall -g -ftree-vectorize -pipe")


set(cxx_sources
flutter/main.cc
flutter/utils.cc
flutter/cpp_client_wrapper/engine_method_result.cc
flutter/cpp_client_wrapper/flutter_window_controller.cc
flutter/cpp_client_wrapper/json_message_codec.cc
flutter/cpp_client_wrapper/plugin_registrar.cc
flutter/cpp_client_wrapper/standard_codec.cc
)

add_executable(flutter ${cxx_sources})
target_link_libraries(flutter ts brcmGLESv2 brcmEGL bcm_host flutter_engine pthread dl flutter_linux)

install(TARGETS flutter RUNTIME DESTINATION bin)
1 change: 1 addition & 0 deletions flutter/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ executable("flutter") {

libs = [
"rt",
"ts",
"brcmEGL",
"brcmGLESv2",
"flutter_engine",
Expand Down
9 changes: 9 additions & 0 deletions flutter/cpp_client_wrapper/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
This code is intended to be built into plugins and applications to provide
higher-level, C++ abstractions for interacting with the Flutter library.

Over time, the goal is to move more of this code into the library in a way that
provides a usable ABI (e.g., does not use standard libary in the interfaces).

Note that this wrapper is still in early stages. Expect significant churn in
both the APIs and the structure of the wrapper (e.g., the exact set of files
that need to be built).
105 changes: 105 additions & 0 deletions flutter/cpp_client_wrapper/byte_stream_wrappers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_BYTE_STREAM_WRAPPERS_H_
#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_BYTE_STREAM_WRAPPERS_H_

// Utility classes for interacting with a buffer of bytes as a stream, for use
// in message channel codecs.

#include <cstdint>
#include <cstring>
#include <iostream>
#include <vector>

namespace flutter {

// Wraps an array of bytes with utility methods for treating it as a readable
// stream.
class ByteBufferStreamReader {
public:
// Createa a reader reading from |bytes|, which must have a length of |size|.
// |bytes| must remain valid for the lifetime of this object.
explicit ByteBufferStreamReader(const uint8_t* bytes, size_t size)
: bytes_(bytes), size_(size) {}

// Reads and returns the next byte from the stream.
uint8_t ReadByte() {
if (location_ >= size_) {
std::cerr << "Invalid read in StandardCodecByteStreamReader" << std::endl;
return 0;
}
return bytes_[location_++];
}

// Reads the next |length| bytes from the stream into |buffer|. The caller
// is responsible for ensuring that |buffer| is large enough.
void ReadBytes(uint8_t* buffer, size_t length) {
if (location_ + length > size_) {
std::cerr << "Invalid read in StandardCodecByteStreamReader" << std::endl;
return;
}
std::memcpy(buffer, &bytes_[location_], length);
location_ += length;
}

// Advances the read cursor to the next multiple of |alignment| relative to
// the start of the wrapped byte buffer, unless it is already aligned.
void ReadAlignment(uint8_t alignment) {
uint8_t mod = location_ % alignment;
if (mod) {
location_ += alignment - mod;
}
}

private:
// The buffer to read from.
const uint8_t* bytes_;
// The total size of the buffer.
size_t size_;
// The current read location.
size_t location_ = 0;
};

// Wraps an array of bytes with utility methods for treating it as a writable
// stream.
class ByteBufferStreamWriter {
public:
// Createa a writter that writes into |buffer|.
// |buffer| must remain valid for the lifetime of this object.
explicit ByteBufferStreamWriter(std::vector<uint8_t>* buffer)
: bytes_(buffer) {
assert(buffer);
}

// Writes |byte| to the wrapped buffer.
void WriteByte(uint8_t byte) { bytes_->push_back(byte); }

// Writes the next |length| bytes from |bytes| into the wrapped buffer.
// The caller is responsible for ensuring that |buffer| is large enough.
void WriteBytes(const uint8_t* bytes, size_t length) {
assert(length > 0);
bytes_->insert(bytes_->end(), bytes, bytes + length);
}

// Writes 0s until the next multiple of |alignment| relative to
// the start of the wrapped byte buffer, unless the write positition is
// already aligned.
void WriteAlignment(uint8_t alignment) {
uint8_t mod = bytes_->size() % alignment;
if (mod) {
for (int i = 0; i < alignment - mod; ++i) {
WriteByte(0);
}
}
}

private:
// The buffer to write to.
std::vector<uint8_t>* bytes_;
};

} // namespace flutter

#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_BYTE_STREAM_WRAPPERS_H_
45 changes: 45 additions & 0 deletions flutter/cpp_client_wrapper/engine_method_result.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "include/flutter/engine_method_result.h"

#include <assert.h>
#include <iostream>

namespace flutter {
namespace internal {

ReplyManager::ReplyManager(BinaryReply reply_handler)
: reply_handler_(std::move(reply_handler)) {
assert(reply_handler_);
}

ReplyManager::~ReplyManager() {
if (reply_handler_) {
// Warn, rather than send a not-implemented response, since the engine may
// no longer be valid at this point.
std::cerr
<< "Warning: Failed to respond to a message. This is a memory leak."
<< std::endl;
}
}

void ReplyManager::SendResponseData(const std::vector<uint8_t>* data) {
if (!reply_handler_) {
std::cerr
<< "Error: Only one of Success, Error, or NotImplemented can be "
"called,"
<< " and it can be called exactly once. Ignoring duplicate result."
<< std::endl;
return;
}

const uint8_t* message = data && !data->empty() ? data->data() : nullptr;
size_t message_size = data ? data->size() : 0;
reply_handler_(message, message_size);
reply_handler_ = nullptr;
}

} // namespace internal
} // namespace flutter
81 changes: 81 additions & 0 deletions flutter/cpp_client_wrapper/flutter_window_controller.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "include/flutter/flutter_window_controller.h"

#include <algorithm>
#include <iostream>

namespace flutter {

FlutterWindowController::FlutterWindowController(
const std::string& icu_data_path)
: icu_data_path_(icu_data_path) {
init_succeeded_ = FlutterDesktopInit();
}

FlutterWindowController::~FlutterWindowController() {
if (controller_) {
FlutterDesktopDestroyWindow(controller_);
}
if (init_succeeded_) {
FlutterDesktopTerminate();
}
}

bool FlutterWindowController::CreateWindow(
int width,
int height,
const std::string& title,
const std::string& assets_path,
const std::vector<std::string>& arguments) {
if (!init_succeeded_) {
std::cerr << "Could not create window; FlutterDesktopInit failed."
<< std::endl;
return false;
}

if (controller_) {
std::cerr << "Only one Flutter window can exist at a time." << std::endl;
return false;
}

std::vector<const char*> engine_arguments;
std::transform(
arguments.begin(), arguments.end(), std::back_inserter(engine_arguments),
[](const std::string& arg) -> const char* { return arg.c_str(); });
size_t arg_count = engine_arguments.size();

controller_ = FlutterDesktopCreateWindow(
width, height, title.c_str(), assets_path.c_str(), icu_data_path_.c_str(),
arg_count > 0 ? &engine_arguments[0] : nullptr, arg_count);
if (!controller_) {
std::cerr << "Failed to create window." << std::endl;
return false;
}
window_ =
std::make_unique<FlutterWindow>(FlutterDesktopGetWindow(controller_));
return true;
}

FlutterDesktopPluginRegistrarRef FlutterWindowController::GetRegistrarForPlugin(
const std::string& plugin_name) {
if (!controller_) {
std::cerr << "Cannot get plugin registrar without a window; call "
"CreateWindow first."
<< std::endl;
return nullptr;
}
return FlutterDesktopGetPluginRegistrar(controller_, plugin_name.c_str());
}

void FlutterWindowController::RunEventLoop() {
if (controller_) {
FlutterDesktopRunWindowLoop(controller_);
}
window_ = nullptr;
controller_ = nullptr;
}

} // namespace flutter
Loading