mirror of https://github.com/mosra/magnum.git
10 changed files with 512 additions and 65 deletions
@ -0,0 +1,109 @@ |
|||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz> |
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a |
||||||
|
copy of this software and associated documentation files (the "Software"), |
||||||
|
to deal in the Software without restriction, including without limitation |
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||||
|
and/or sell copies of the Software, and to permit persons to whom the |
||||||
|
Software is furnished to do so, subject to the following conditions: |
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included |
||||||
|
in all copies or substantial portions of the Software. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||||
|
DEALINGS IN THE SOFTWARE. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include "WindowlessNaClApplication.h" |
||||||
|
|
||||||
|
#include <ppapi/cpp/graphics_3d.h> |
||||||
|
#include <ppapi/cpp/completion_callback.h> |
||||||
|
#include <Utility/NaClStreamBuffer.h> |
||||||
|
|
||||||
|
#include "Context.h" |
||||||
|
|
||||||
|
namespace Magnum { namespace Platform { |
||||||
|
|
||||||
|
struct WindowlessNaClApplication::ConsoleDebugOutput { |
||||||
|
explicit ConsoleDebugOutput(pp::Instance* instance); |
||||||
|
|
||||||
|
Utility::NaClConsoleStreamBuffer debugBuffer, warningBuffer, errorBuffer; |
||||||
|
std::ostream debugOutput, warningOutput, errorOutput; |
||||||
|
}; |
||||||
|
|
||||||
|
WindowlessNaClApplication::ConsoleDebugOutput::ConsoleDebugOutput(pp::Instance* instance): debugBuffer(instance, Utility::NaClConsoleStreamBuffer::LogLevel::Log), warningBuffer(instance, Utility::NaClConsoleStreamBuffer::LogLevel::Warning), errorBuffer(instance, Utility::NaClConsoleStreamBuffer::LogLevel::Error), debugOutput(&debugBuffer), warningOutput(&warningBuffer), errorOutput(&errorBuffer) { |
||||||
|
/* Inform about this change on standard output */ |
||||||
|
Debug() << "Platform::NaClApplication: redirecting Debug, Warning and Error output to JavaScript console"; |
||||||
|
|
||||||
|
Debug::setOutput(&debugOutput); |
||||||
|
Warning::setOutput(&warningOutput); |
||||||
|
Error::setOutput(&errorOutput); |
||||||
|
} |
||||||
|
|
||||||
|
WindowlessNaClApplication::WindowlessNaClApplication(const Arguments& arguments): Instance(arguments), Graphics3DClient(this), c(nullptr) { |
||||||
|
debugOutput = new ConsoleDebugOutput(this); |
||||||
|
createContext(new Configuration); |
||||||
|
} |
||||||
|
|
||||||
|
WindowlessNaClApplication::WindowlessNaClApplication(const Arguments& arguments, Configuration* configuration): Instance(arguments), Graphics3DClient(this), graphics(nullptr), c(nullptr) { |
||||||
|
debugOutput = new ConsoleDebugOutput(this); |
||||||
|
if(configuration) createContext(configuration); |
||||||
|
} |
||||||
|
|
||||||
|
void WindowlessNaClApplication::createContext(Configuration* configuration) { |
||||||
|
if(!tryCreateContext(configuration)) { |
||||||
|
Error() << "Platform::WindowlessNaClApplication::createContext(): cannot create context"; |
||||||
|
delete configuration; |
||||||
|
std::exit(1); |
||||||
|
|
||||||
|
} else delete configuration; |
||||||
|
} |
||||||
|
|
||||||
|
bool WindowlessNaClApplication::tryCreateContext(Configuration* configuration) { |
||||||
|
CORRADE_ASSERT(!c, "Platform::WindowlessNaClApplication::tryCreateContext(): context already created", false); |
||||||
|
|
||||||
|
const std::int32_t attributes[] = { |
||||||
|
PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8, |
||||||
|
PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24, |
||||||
|
PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8, |
||||||
|
PP_GRAPHICS3DATTRIB_WIDTH, 1, |
||||||
|
PP_GRAPHICS3DATTRIB_HEIGHT, 1, |
||||||
|
PP_GRAPHICS3DATTRIB_NONE |
||||||
|
}; |
||||||
|
|
||||||
|
graphics = new pp::Graphics3D(this, attributes); |
||||||
|
if(graphics->is_null()) { |
||||||
|
delete graphics; |
||||||
|
graphics = nullptr; |
||||||
|
return false; |
||||||
|
} |
||||||
|
if(!BindGraphics(*graphics)) { |
||||||
|
Error() << "Platform::WindowlessNaClApplication::tryCreateContext(): cannot bind graphics"; |
||||||
|
std::exit(1); |
||||||
|
} |
||||||
|
|
||||||
|
glSetCurrentContextPPAPI(graphics->pp_resource()); |
||||||
|
|
||||||
|
c = new Context; |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
WindowlessNaClApplication::~WindowlessNaClApplication() { |
||||||
|
delete c; |
||||||
|
delete graphics; |
||||||
|
delete debugOutput; |
||||||
|
} |
||||||
|
|
||||||
|
bool WindowlessNaClApplication::Init(uint32_t , const char* , const char*) { |
||||||
|
return exec() == 0; |
||||||
|
} |
||||||
|
|
||||||
|
}} |
||||||
@ -0,0 +1,201 @@ |
|||||||
|
#ifndef Magnum_Platform_WindowlessNaClApplication_h |
||||||
|
#define Magnum_Platform_WindowlessNaClApplication_h |
||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz> |
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a |
||||||
|
copy of this software and associated documentation files (the "Software"), |
||||||
|
to deal in the Software without restriction, including without limitation |
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||||
|
and/or sell copies of the Software, and to permit persons to whom the |
||||||
|
Software is furnished to do so, subject to the following conditions: |
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included |
||||||
|
in all copies or substantial portions of the Software. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||||
|
DEALINGS IN THE SOFTWARE. |
||||||
|
*/ |
||||||
|
|
||||||
|
/** @file
|
||||||
|
* @brief Class Magnum::Platform::WindowlessNaClApplication |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <string> |
||||||
|
#include <Containers/EnumSet.h> |
||||||
|
#include <ppapi/cpp/instance.h> |
||||||
|
#include <ppapi/cpp/module.h> |
||||||
|
#include <ppapi/cpp/graphics_3d_client.h> |
||||||
|
#include <ppapi/gles2/gl2ext_ppapi.h> |
||||||
|
|
||||||
|
#include "Math/Vector2.h" |
||||||
|
#include "Magnum.h" |
||||||
|
|
||||||
|
#include "corradeCompatibility.h" |
||||||
|
|
||||||
|
namespace pp { |
||||||
|
class Graphics3D; |
||||||
|
class Fullscreen; |
||||||
|
} |
||||||
|
|
||||||
|
namespace Magnum { namespace Platform { |
||||||
|
|
||||||
|
/** @nosubgrouping
|
||||||
|
@brief Windowless NaCl application |
||||||
|
|
||||||
|
Application running in [Google Chrome Native Client](https://developers.google.com/native-client/).
|
||||||
|
See @ref platform for brief introduction. |
||||||
|
|
||||||
|
@section WindowlessNaClApplication-usage Usage |
||||||
|
|
||||||
|
Place your code into exec(). The subclass must be then registered to NaCl API |
||||||
|
using MAGNUM_WINDOWLESSNACLAPPLICATION_MAIN() macro. |
||||||
|
@code |
||||||
|
class MyApplication: public Magnum::Platform::WindowlessNaClApplication { |
||||||
|
// implement required methods...
|
||||||
|
}; |
||||||
|
MAGNUM_WINDOWLESSNACLAPPLICATION_MAIN(MyApplication) |
||||||
|
@endcode |
||||||
|
|
||||||
|
If no other application header is included this class is also aliased to |
||||||
|
`Platform::WindowlessApplication` and the macro is aliased to |
||||||
|
`MAGNUM_WINDOWLESSAPPLICATION_MAIN()` to simplify porting. |
||||||
|
|
||||||
|
@section WindowlessNaClApplication-html HTML markup and NMF file |
||||||
|
|
||||||
|
You need to provide HTML markup containing `<embed>` pointing to `*.nmf` |
||||||
|
file describing the application. |
||||||
|
|
||||||
|
@todoc Document this better, add "bootstrap" examples |
||||||
|
|
||||||
|
@subsection WindowlessNaClApplication-html-console Redirecting output to Chrome's JavaScript console |
||||||
|
|
||||||
|
The application redirects @ref Corrade::Utility::Debug "Debug", |
||||||
|
@ref Corrade::Utility::Warning "Warning" and @ref Corrade::Utility::Error "Error" |
||||||
|
output to JavaScript console. See also @ref Corrade::Utility::NaClConsoleStreamBuffer |
||||||
|
for more information. |
||||||
|
*/ |
||||||
|
class WindowlessNaClApplication: public pp::Instance, public pp::Graphics3DClient { |
||||||
|
public: |
||||||
|
/** @brief Application arguments */ |
||||||
|
typedef PP_Instance Arguments; |
||||||
|
|
||||||
|
class Configuration; |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Default constructor |
||||||
|
* @param arguments Application arguments |
||||||
|
* |
||||||
|
* Creates application with default configuration. See Configuration |
||||||
|
* for more information. |
||||||
|
*/ |
||||||
|
explicit WindowlessNaClApplication(const Arguments& arguments); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructor |
||||||
|
* @param arguments Application arguments |
||||||
|
* @param configuration Configuration |
||||||
|
* |
||||||
|
* The @p configuration is deleted afterwards. If `nullptr` is passed |
||||||
|
* as @p configuration, the context is not created and must be created |
||||||
|
* with createContext(). |
||||||
|
*/ |
||||||
|
explicit WindowlessNaClApplication(const Arguments& arguments, Configuration* configuration); |
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Execute application |
||||||
|
* @return Value for returning from `main()`. |
||||||
|
*/ |
||||||
|
virtual int exec() = 0; |
||||||
|
|
||||||
|
protected: |
||||||
|
/* Nobody will need to have (and delete) WindowlessNaClApplication*,
|
||||||
|
thus this is faster than public pure virtual destructor */ |
||||||
|
~WindowlessNaClApplication(); |
||||||
|
|
||||||
|
/** @copydoc GlutApplication::createContext() */ |
||||||
|
void createContext(Configuration* configuration); |
||||||
|
|
||||||
|
/** @copydoc GlutApplication::tryCreateContext() */ |
||||||
|
bool tryCreateContext(Configuration* configuration); |
||||||
|
|
||||||
|
private: |
||||||
|
struct ConsoleDebugOutput; |
||||||
|
|
||||||
|
void Graphics3DContextLost() override { |
||||||
|
CORRADE_ASSERT(false, "NaClApplication: context unexpectedly lost", ); |
||||||
|
} |
||||||
|
|
||||||
|
bool Init(std::uint32_t, const char*, const char*) override; |
||||||
|
|
||||||
|
pp::Graphics3D* graphics; |
||||||
|
Context* c; |
||||||
|
ConsoleDebugOutput* debugOutput; |
||||||
|
}; |
||||||
|
|
||||||
|
/**
|
||||||
|
@brief %Configuration |
||||||
|
|
||||||
|
@see WindowlessNaClApplication(), createContext(), tryCreateContext() |
||||||
|
*/ |
||||||
|
class WindowlessNaClApplication::Configuration { |
||||||
|
Configuration(const Configuration&) = delete; |
||||||
|
Configuration(Configuration&&) = delete; |
||||||
|
Configuration& operator=(const Configuration&) = delete; |
||||||
|
Configuration& operator=(Configuration&&) = delete; |
||||||
|
|
||||||
|
public: |
||||||
|
constexpr explicit Configuration() {} |
||||||
|
}; |
||||||
|
|
||||||
|
namespace Implementation { |
||||||
|
template<class Application> class WindowlessNaClModule: public pp::Module { |
||||||
|
public: |
||||||
|
~WindowlessNaClModule() { glTerminatePPAPI(); } |
||||||
|
|
||||||
|
bool Init() override { |
||||||
|
return glInitializePPAPI(get_browser_interface()); |
||||||
|
} |
||||||
|
|
||||||
|
pp::Instance* CreateInstance(PP_Instance instance) { |
||||||
|
return new Application(instance); |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
/** @hideinitializer
|
||||||
|
@brief Entry point for windowless NaCl application |
||||||
|
@param application Application class name |
||||||
|
|
||||||
|
See WindowlessNaClApplication and @ref portability-applications for more |
||||||
|
information. When no other windowless application header is included this macro |
||||||
|
is also aliased to `MAGNUM_WINDOWLESSAPPLICATION_MAIN()`. |
||||||
|
*/ |
||||||
|
/* look at that insane placement of __attribute__. WTF. */ |
||||||
|
#define MAGNUM_WINDOWLESSNACLAPPLICATION_MAIN(application) \ |
||||||
|
namespace pp { \
|
||||||
|
Module __attribute__ ((visibility ("default"))) * CreateModule(); \
|
||||||
|
Module __attribute__ ((visibility ("default"))) * CreateModule() { \
|
||||||
|
return new Magnum::Platform::Implementation::WindowlessNaClModule<application>(); \
|
||||||
|
} \
|
||||||
|
} |
||||||
|
|
||||||
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||||
|
#ifndef MAGNUM_WINDOWLESSAPPLICATION_MAIN |
||||||
|
typedef WindowlessNaClApplication WindowlessApplication; |
||||||
|
#define MAGNUM_WINDOWLESSAPPLICATION_MAIN(className) MAGNUM_WINDOWLESSNACLAPPLICATION_MAIN(className) |
||||||
|
#else |
||||||
|
#undef MAGNUM_WINDOWLESSAPPLICATION_MAIN |
||||||
|
#endif |
||||||
|
#endif |
||||||
|
|
||||||
|
}} |
||||||
|
|
||||||
|
#endif |
||||||
@ -0,0 +1,91 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html> |
||||||
|
<head> |
||||||
|
<title>Magnum Info</title> |
||||||
|
<style type="text/css"> |
||||||
|
body { |
||||||
|
margin: 0px; |
||||||
|
padding: 0px; |
||||||
|
font-family: sans-serif; |
||||||
|
background-color: #111111; |
||||||
|
color: #aaaaaa; |
||||||
|
} |
||||||
|
|
||||||
|
h1 { |
||||||
|
text-align: center; |
||||||
|
font-size: 20px; |
||||||
|
} |
||||||
|
|
||||||
|
#listener { |
||||||
|
border-style: solid; |
||||||
|
border-color: #333333; |
||||||
|
border-width: 1px; |
||||||
|
padding: 1px; |
||||||
|
width: 640px; |
||||||
|
height: 480px; |
||||||
|
margin-left: auto; |
||||||
|
margin-right: auto; |
||||||
|
margin-top: 20px; |
||||||
|
margin-bottom: 20px; |
||||||
|
position: relative; |
||||||
|
} |
||||||
|
|
||||||
|
#module { |
||||||
|
visibility: hidden; |
||||||
|
position: absolute; |
||||||
|
} |
||||||
|
|
||||||
|
#info { |
||||||
|
width: 640px; |
||||||
|
height: 480px; |
||||||
|
overflow: auto; |
||||||
|
font-family: monospace; |
||||||
|
white-space: pre-wrap; |
||||||
|
} |
||||||
|
|
||||||
|
#status { |
||||||
|
position: absolute; |
||||||
|
width: 640px; |
||||||
|
text-align: center; |
||||||
|
top: 200px; |
||||||
|
font-size: 30px; |
||||||
|
font-weight: bold; |
||||||
|
z-index: 9; |
||||||
|
} |
||||||
|
</style> |
||||||
|
</head> |
||||||
|
<body onload="pageLoaded();"> |
||||||
|
<h1>Magnum Info</h1> |
||||||
|
<div id="listener"> |
||||||
|
<script type="text/javascript"> |
||||||
|
var module = null; |
||||||
|
|
||||||
|
function pageLoaded() { |
||||||
|
if(!module) setStatus('Loading...'); |
||||||
|
} |
||||||
|
|
||||||
|
function moduleLoaded() { |
||||||
|
module = document.getElementById('module'); |
||||||
|
setStatus(''); |
||||||
|
} |
||||||
|
|
||||||
|
function messageReceived(message) { |
||||||
|
var info = document.getElementById('info'); |
||||||
|
info.innerHTML += message.data; |
||||||
|
} |
||||||
|
|
||||||
|
function setStatus(message) { |
||||||
|
var status = document.getElementById('status'); |
||||||
|
if(status) status.innerHTML = message; |
||||||
|
} |
||||||
|
|
||||||
|
var listener = document.getElementById('listener'); |
||||||
|
listener.addEventListener('load', moduleLoaded, true); |
||||||
|
listener.addEventListener('message', messageReceived, true); |
||||||
|
</script> |
||||||
|
<embed name="nacl" id="module" type="application/x-nacl" src="magnum-info.nmf" /> |
||||||
|
<div id="status">Initialization...</div> |
||||||
|
<div id="info"></div> |
||||||
|
</div> |
||||||
|
</body> |
||||||
|
</html> |
||||||
@ -0,0 +1,6 @@ |
|||||||
|
{ |
||||||
|
"program": { |
||||||
|
"x86-32": {"url": "magnum-info-x86-32.nexe"}, |
||||||
|
"x86-64": {"url": "magnum-info-x86-64.nexe"} |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue