Skip to content
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

[wip] Headless GL #1494

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ matrix:
- libicu-dev
- libfreetype6-dev
- libharfbuzz-dev
- libosmesa-dev
- os: linux
env: PLATFORM=android
addons:
Expand Down
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,7 @@ if(BENCHMARK)
message(STATUS "Build with benchmarks")
add_subdirectory(${PROJECT_SOURCE_DIR}/bench)
endif()

if(PAPARAZZI)
add_subdirectory(${PROJECT_SOURCE_DIR}/paparazzi)
endif()
2 changes: 2 additions & 0 deletions core/src/gl/framebuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ void FrameBuffer::apply(RenderState& _rs, GLuint _handle, glm::vec2 _viewport, g
// Enable depth testing
_rs.depthMask(GL_TRUE);

_rs.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);

// Setup raster state
_rs.culling(GL_TRUE);
_rs.cullFace(GL_BACK);
Expand Down
71 changes: 71 additions & 0 deletions paparazzi/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
### Worker

include(${CMAKE_CURRENT_SOURCE_DIR}/prime_server.cmake)

# use, i.e. don't skip the full RPATH for the build tree
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
SET(CMAKE_INSTALL_RPATH ${CMAKE_BINARY_DIR}/lib ${CMAKE_INSTALL_RPATH})

# the RPATH to be used when installing, but only if it's not a system directory
# LIST(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/lib" isSystemDir)
# IF("${isSystemDir}" STREQUAL "-1")
# SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
# ENDIF("${isSystemDir}" STREQUAL "-1")

# if (USE_SYSTEM_OSMESA_LIBS)
# include(FindPkgConfig)
# pkg_check_modules(OSMesa REQUIRED osmesa)
# else ()
# include(${PROJECT_SOURCE_DIR}/toolchains/mesa.cmake)
# endif()


add_executable(paparazzi_worker
src/worker.cpp
src/paparazzi.cpp
src/stb_image.cpp)

target_include_directories(paparazzi_worker
PUBLIC
src/tools
${PROJECT_SOURCE_DIR}/platforms/common
${PROJECT_SOURCE_DIR}/platforms/linux/src
${OSMesa_INCLUDE_DIRS}
${prime_server_INCLUDE_DIRS})

target_link_libraries(paparazzi_worker
core
headless_context
-lpthread
-lOSMesa
-lGL
${prime_server_LIBRARIES}
${PRIME_SERVER_DEPS_LIBRARIES}
)

target_compile_definitions(paparazzi_worker
PRIVATE
PLATFORM_HEADLESS=1)

target_link_libraries(paparazzi_worker
platform_linux)

add_dependencies(paparazzi_worker external-prime_server)

### Proxy

add_executable(paparazzi_proxy
src/proxy.cpp)

target_include_directories(paparazzi_proxy
PUBLIC
${prime_server_INCLUDE_DIRS})

target_link_libraries(paparazzi_proxy
${prime_server_LIBRARIES}
${PRIME_SERVER_DEPS_LIBRARIES}
)

add_dependencies(paparazzi_proxy external-prime_server)
42 changes: 42 additions & 0 deletions paparazzi/prime_server.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
include(FindPkgConfig)

pkg_check_modules(PRIME_SERVER_DEPS REQUIRED libzmq>=4.1.3 libczmq>=3.0 libcurl>=7.22.0)

include(ExternalProject)

ExternalProject_Add(
external-prime_server

GIT_REPOSITORY "https://github.com/kevinkreiser/prime_server.git"

UPDATE_COMMAND ""
PATCH_COMMAND ""

BUILD_IN_SOURCE 1
SOURCE_DIR "${CMAKE_BINARY_DIR}/prime_server"
#BINARY_DIR "${CMAKE_BINARY_DIR}/prime_server-build"

CONFIGURE_COMMAND "${CMAKE_BINARY_DIR}/prime_server/autogen.sh" && "${CMAKE_BINARY_DIR}/prime_server/configure" --prefix=<INSTALL_DIR>

BUILD_COMMAND make

TEST_COMMAND ""

INSTALL_COMMAND make install
)

set(external-prime_server_CXXFLAGS "-lpthread")

ExternalProject_Get_Property(external-prime_server install_dir)

ExternalProject_Add_Step(
external-prime_server CopyToBin
COMMAND ${CMAKE_COMMAND} -E copy_directory ${install_dir}/bin ${CMAKE_BINARY_DIR}/bin
COMMAND ${CMAKE_COMMAND} -E copy_directory ${install_dir}/lib ${CMAKE_BINARY_DIR}/lib
DEPENDEES install
)

set(prime_server_INCLUDE_DIRS "${install_dir}/include")
set(prime_server_LIBRARIES "${CMAKE_SHARED_LIBRARY_PREFIX}prime_server${CMAKE_SHARED_LIBRARY_SUFFIX}")

link_directories(${CMAKE_BINARY_DIR}/lib)
182 changes: 182 additions & 0 deletions paparazzi/src/paparazzi.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
#include "paparazzi.h"

#define AA_SCALE 1.0
#define IMAGE_DEPTH 4

#if PLATFORM_LINUX
#include "platform_linux.h"
#elif PLATFORM_OSX
#include "platform_osx.h"
#endif

#include "log.h"
#include "gl/texture.h"

#include "hash-library/md5.h"

#include <functional>
#include <csignal>
#include <fstream>
#include <sstream>
#include <sys/time.h>
#include <unistd.h>
#include "glm/trigonometric.hpp"

#include "stb_image_write.h"


using namespace Tangram;

unsigned long long timeStart;

double getTime() {
static struct timeval tv;

gettimeofday(&tv, NULL);
return ((unsigned long long)(tv.tv_sec) * 1000 + (unsigned long long)(tv.tv_usec) / 1000) * 0.001;
}

Paparazzi::Paparazzi() {

m_glContext = std::make_unique<HeadlessContext>();
if (!m_glContext->init()) {
throw std::runtime_error("Could not initialize GL context");
}
m_glContext->resize(1, 1);
if (!m_glContext->makeCurrent()) {
throw std::runtime_error("Could not activate GL context");
}

#if PLATFORM_LINUX
UrlClient::Options urlClientOptions;
urlClientOptions.numberOfThreads = 10;
auto platform = std::make_shared<LinuxPlatform>(urlClientOptions);
#elif PLATFORM_OSX
auto platform = std::make_shared<OSXPlatform>();
#endif

timeStart = getTime();

m_map = std::unique_ptr<Tangram::Map>(new Tangram::Map(platform));

setScene("scene.yaml");

m_map->setupGL();
m_map->setPixelScale(AA_SCALE);

//m_map->resize(m_width*AA_SCALE, m_height*AA_SCALE);
//m_glContext->setScale(AA_SCALE);
//setSize(m_width, m_height, 1.0);

Tangram::setDebugFlag(DebugFlags::tile_bounds, true);

logMsg("Done Init!\n");

}

Paparazzi::~Paparazzi() {
}

void Paparazzi::setSize (const int &_width, const int &_height, const float &_density) {
if (_density*_width == m_width && _density*_height == m_height &&
_density*AA_SCALE == m_map->getPixelScale()) { return; }

m_width = _width*_density;
m_height = _height*_density;

// Setup the size of the image
if (_density*AA_SCALE != m_map->getPixelScale()) {
m_map->setPixelScale(_density*AA_SCALE);
}
m_map->resize(m_width*AA_SCALE, m_height*AA_SCALE);

m_glContext->resize(m_width, m_height);
}

void Paparazzi::setZoom(const float &_zoom) {
if (_zoom == m_zoom) { return; }
m_zoom = _zoom;
m_map->setZoom(_zoom);
}

void Paparazzi::setTilt(const float &_deg) {
if (_deg == m_tilt) { return; }
m_tilt = _deg;
m_map->setTilt(glm::radians(m_tilt));
}
void Paparazzi::setRotation(const float &_deg) {
if (_deg == m_rotation) { return; }

m_rotation = _deg;
m_map->setRotation(glm::radians(m_rotation));
}

void Paparazzi::setPosition(const double &_lon, const double &_lat) {
if (_lon == m_lon && _lat == m_lat) { return; }

m_lon = _lon;
m_lat = _lat;
m_map->setPosition(m_lon, m_lat);
}

void Paparazzi::setScene(const std::string &_url) {
if (_url == m_scene) { return; }
m_scene = _url;
m_map->loadScene(m_scene.c_str(), false,
{SceneUpdate("global.sdk_mapzen_api_key", m_apiKey)});
}

void Paparazzi::setSceneContent(const std::string &_yaml_content) {
MD5 md5;
std::string md5_scene = md5(_yaml_content);

if (md5_scene == m_scene) { return; }
m_scene = md5_scene;

// TODO:
// - This is waiting for LoadSceneConfig to be implemented in Tangram::Map
// Once that's done there is no need to save the file.
std::string name = "cache/"+md5_scene+".yaml";
std::ofstream out(name.c_str());
out << _yaml_content.c_str();
out.close();

m_map->loadScene(name.c_str(), false, {SceneUpdate("global.sdk_mapzen_api_key", m_apiKey)});
}

bool Paparazzi::update(int32_t _maxWaitTime) {
double startTime = getTime();
float delta = 0.0;

while (_maxWaitTime < 0 || delta < _maxWaitTime) {

bool bFinish = m_map->update(10.);
delta = float(getTime() - startTime);

if (bFinish) {
LOG("Update: Finish!\n");
return true;
}
usleep(10000);
}
LOG("Update: Done waiting...\n");
return false;
}

void Paparazzi::render(std::string& _image) {
m_glContext->makeCurrent();

m_map->render();

GL::finish();

stbi_write_png_to_func(
[](void *context, void *data, int size) {
static_cast<std::string*>(context)->append(static_cast<const char*>(data), size); },
&_image,
m_glContext->width(),
m_glContext->height(),
IMAGE_DEPTH,
m_glContext->buffer(),
m_glContext->width() * IMAGE_DEPTH);
}
40 changes: 40 additions & 0 deletions paparazzi/src/paparazzi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

#include <memory>
#include <string>

#include "tangram.h"
#include "headlessContext.h"

class Paparazzi {
public:
Paparazzi();
~Paparazzi();

void setSize(const int &_width, const int &_height, const float &_density);
void setZoom(const float &_zoom);
void setTilt(const float &_deg);
void setRotation(const float &_deg);
void setScene(const std::string &_url);
void setSceneContent(const std::string &_yaml_content);
void setPosition(const double &_lon, const double &_lat);
void render(std::string& _image);
bool update(int32_t _maxWaitTime = -1);

void setApiKey(const std::string &_apiKey) { m_apiKey = _apiKey; }

protected:

std::string m_scene;
std::string m_apiKey;
double m_lat = 0.0;
double m_lon = 0.0;
float m_zoom = 0.0f;
float m_rotation = 0.0f;
float m_tilt = 0.0f;
int m_width = 0;
int m_height = 0;

std::unique_ptr<Tangram::Map> m_map;
std::unique_ptr<Tangram::HeadlessContext> m_glContext;
};
Loading