From 4f6d4e8abef99e14d9cbd3af9128ba2f2333138d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Tue, 15 Apr 2014 18:47:12 -0400 Subject: [PATCH] first cut at headless rendering refs #141 --- Makefile | 14 ++++- test/headless.cpp | 141 ++++++++++++++++++++++++++++++++++++++++++++++ test/test.gyp | 34 +++++++++++ 3 files changed, 186 insertions(+), 3 deletions(-) create mode 100644 test/headless.cpp diff --git a/Makefile b/Makefile index b47e84c8d..7faf0c739 100644 --- a/Makefile +++ b/Makefile @@ -14,16 +14,23 @@ llmr: config.gypi llmr.gyp ##### Test cases ############################################################### -# Runs the test cases -test: config.gypi test/test.gyp +build/test/Makefile: config.gypi test/test.gyp deps/run_gyp test/test.gyp --depth=. -Goutput_dir=.. --generator-output=./build/test -f make + +test: build/test/Makefile make -C build/test V=$(V) test +# Runs all test cases run-tests: test @for FILE in build/Release/test_*; do \ $${FILE}; \ done +# Only runs headless test case +run-headless-test: build/test/Makefile + make -C build/test BUILDTYPE=Debug V=$(V) headless + build/Debug/test_headless + ##### Makefile builds ########################################################## @@ -60,8 +67,9 @@ lproj: config.gypi linux/llmr-app.gyp clean: -rm -rf ./build/Release + -rm -rf ./build/Debug distclean: clean -rm -rf ./build -.PHONY: llmr test linux +.PHONY: llmr test linux build/test/Makefile diff --git a/test/headless.cpp b/test/headless.cpp new file mode 100644 index 000000000..af9f56acd --- /dev/null +++ b/test/headless.cpp @@ -0,0 +1,141 @@ +#include +#include "gtest/gtest.h" + + + + +#include +#include +#include + +double llmr::platform::elapsed() { + return 0; +} + +void llmr::platform::restart() { + // TODO +} + +std::shared_ptr +llmr::platform::request_http(const std::string &url, std::function background_function, + std::function foreground_callback) { + // TODO + return nullptr; +} + +void llmr::platform::cancel_request_http(const std::shared_ptr &req) { + // TODO +} + + + + + +TEST(Headless, initialize) { + llmr::Settings settings; + + llmr::Map map(settings); + + + // Setup OpenGL + CGLContextObj gl_context; + + // TODO: test if OpenGL 4.1 with GL_ARB_ES2_compatibility is supported + // If it is, use kCGLOGLPVersion_3_2_Core and enable that extension. + CGLPixelFormatAttribute attributes[] = { + kCGLPFAOpenGLProfile, + (CGLPixelFormatAttribute) kCGLOGLPVersion_Legacy, + kCGLPFAAccelerated, + kCGLPFAColorSize, (CGLPixelFormatAttribute)24, + kCGLPFAAlphaSize, (CGLPixelFormatAttribute)8, + kCGLPFAStencilSize, (CGLPixelFormatAttribute)8, + kCGLPFADepthSize, (CGLPixelFormatAttribute)24, + (CGLPixelFormatAttribute) 0 + }; + + CGLPixelFormatObj pixelFormat; + GLint num; + CGLError error = CGLChoosePixelFormat(attributes, &pixelFormat, &num); + if (error) { + fprintf(stderr, "Error pixel format\n"); + return; + } + + error = CGLCreateContext(pixelFormat, NULL, &gl_context); + CGLDestroyPixelFormat(pixelFormat); + if (error) { + fprintf(stderr, "Error creating GL context object\n"); + return; + } + + error = CGLSetCurrentContext(gl_context); + if (error) { + fprintf(stderr, "Switching OpenGL context failed\n"); + return; + } + + + int width = 1024; + int height = 768; + + // Create depth/stencil buffer + GLuint fbo_depth_stencil = 0; + glGenRenderbuffersEXT(1, &fbo_depth_stencil); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo_depth_stencil); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, width, height); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER_EXT, fbo_depth_stencil); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + + GLuint fbo_color = 0; + glGenRenderbuffersEXT(1, &fbo_color); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo_color); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, width, height); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, fbo_color); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + + + GLuint fbo = 0; + glGenFramebuffersEXT(1, &fbo); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo); + + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, fbo_color); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo_depth_stencil); + + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + + if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { + fprintf(stderr, "Couldn't create framebuffer: "); + switch (status) { + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: fprintf(stderr, "incomplete attachment\n"); break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: fprintf(stderr, "incomplete missing attachment\n"); break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: fprintf(stderr, "incomplete draw buffer\n"); break; + case GL_FRAMEBUFFER_UNSUPPORTED: fprintf(stderr, "unsupported\n"); break; + default: fprintf(stderr, "other\n"); break; + } + return; + } + + map.setup(); + map.resize(width, height); + map.loadSettings(); + + map.update(); + map.render(); + + + uint32_t *pixels = new uint32_t[width * height]; + + glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + + std::string result = llmr::util::compress_png(width, height, pixels); + llmr::util::write_file("out.png", result); + + delete[] pixels; + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glDeleteFramebuffersEXT(1, &fbo); + glDeleteTextures(1, &fbo_color); + glDeleteRenderbuffersEXT(1, &fbo_depth_stencil); + + CGLDestroyContext(gl_context); +} diff --git a/test/test.gyp b/test/test.gyp index a9c55ed9a..a04b4ba78 100644 --- a/test/test.gyp +++ b/test/test.gyp @@ -4,6 +4,23 @@ '../config.gypi' ], 'targets': [ + { + 'target_name': 'link_gl', + 'type': 'none', + 'direct_dependent_settings': { + 'conditions': [ + ['OS == "mac"', { + 'link_settings': { + 'libraries': [ + '-framework OpenGL', + ], + }, + }, { + # TODO: add OpenGL link settings for linux + }], + ], + }, + }, { "target_name": "rotation_range", "product_name": "test_rotation_range", @@ -20,6 +37,23 @@ "../llmr.gyp:llmr-x86" ] }, + { + "target_name": "headless", + "product_name": "test_headless", + "type": "executable", + "libraries": [ + "-lpthread", + ], + "sources": [ + "./main.cpp", + "./headless.cpp", + ], + "dependencies": [ + "../deps/gtest/gtest.gyp:gtest", + "../llmr.gyp:llmr-x86", + "link_gl", + ] + }, { "target_name": "test", "type": "none",