Refactored OpenGL embedder that works on Android, Mac or Linux.

To build on/for linux: tools/build.py -a x64 samples
To build on/for Mac: tools/build.py -a ia32 samples
To build on Linux for Android: tools/bui8ld.py --os=android samples

Note that to run on a Mac, you need to delete the first line of the
fragment shader in raytrace.dart, that says:

  precision mediump float;
Review URL: https://codereview.chromium.org//11883013

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@17161 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
gram@google.com 2013-01-16 21:17:52 +00:00
parent d8e322afad
commit 9703d7bfdd
44 changed files with 3788 additions and 11 deletions

View file

@ -117,19 +117,26 @@
'target_name': 'samples',
'type': 'none',
'conditions': [
['OS=="android"', {
'dependencies': [
'samples/android_sample/android_sample.gyp:android_sample',
],
['OS=="android"', {
'dependencies': [
'samples/android_sample/android_sample.gyp:android_sample',
],
},
],
['OS!="android"', {
'dependencies': [
'samples/sample_extension/sample_extension.gyp:sample_extension',
],
['OS=="win"', {
'dependencies': [
'samples/sample_extension/sample_extension.gyp:sample_extension',
],
},
]
],
],
['OS=="mac" or OS=="linux"', {
'dependencies': [
'samples/sample_extension/sample_extension.gyp:sample_extension',
'samples/mobile_emulator_sample/mobile_emulator_sample.gyp:mobile_emulator_sample',
],
},
],
]
},
{
'target_name': 'packages',

View file

@ -7,7 +7,7 @@
'tools/gyp/runtime-configurations.gypi',
'vm/vm.gypi',
'bin/bin.gypi',
'embedders/android/android_embedder.gypi',
'embedders/openglui/openglui_embedder.gypi',
'third_party/double-conversion/src/double-conversion.gypi',
'third_party/jscre/jscre.gypi',
'../tools/gyp/source_filter.gypi',

View file

@ -0,0 +1,81 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "embedders/openglui/android/android_graphics_handler.h"
#include "embedders/openglui/common/log.h"
AndroidGraphicsHandler::AndroidGraphicsHandler(android_app* application)
: GLGraphicsHandler(),
application_(application),
display_(EGL_NO_DISPLAY),
surface_(EGL_NO_SURFACE),
context_(EGL_NO_CONTEXT) {
}
int32_t AndroidGraphicsHandler::Start() {
EGLint format, numConfigs;
EGLConfig config;
const EGLint attributes[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};
static const EGLint ctx_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (display_ != EGL_NO_DISPLAY) {
LOGI("eglInitialize");
if (eglInitialize(display_, NULL, NULL)) {
LOGI("eglChooseConfig");
if (eglChooseConfig(display_, attributes, &config, 1, &numConfigs) &&
numConfigs > 0) {
LOGI("eglGetConfigAttrib");
if (eglGetConfigAttrib(display_, config,
EGL_NATIVE_VISUAL_ID, &format)) {
ANativeWindow_setBuffersGeometry(application_->window, 0, 0, format);
surface_ = eglCreateWindowSurface(display_, config,
(EGLNativeWindowType)application_->window, NULL);
if (surface_ != EGL_NO_SURFACE) {
LOGI("eglCreateContext");
context_ = eglCreateContext(display_, config, EGL_NO_CONTEXT,
ctx_attribs);
if (context_ != EGL_NO_CONTEXT) {
if (eglMakeCurrent(display_, surface_, surface_, context_) &&
eglQuerySurface(display_, surface_, EGL_WIDTH, &width_) &&
width_ > 0 &&
eglQuerySurface(display_, surface_, EGL_HEIGHT, &height_) &&
height_ > 0) {
SetViewport(0, 0, width_, height_);
return 0;
}
}
}
}
}
}
}
LOGE("Error starting graphics");
Stop();
return -1;
}
void AndroidGraphicsHandler::Stop() {
LOGI("Stopping graphics");
if (display_ != EGL_NO_DISPLAY) {
eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (context_ != EGL_NO_CONTEXT) {
eglDestroyContext(display_, context_);
context_ = EGL_NO_CONTEXT;
}
if (surface_ != EGL_NO_SURFACE) {
eglDestroySurface(display_, surface_);
surface_ = EGL_NO_SURFACE;
}
eglTerminate(display_);
display_ = EGL_NO_DISPLAY;
}
}

View file

@ -0,0 +1,26 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_ANDROID_ANDROID_GRAPHICS_HANDLER_H_
#define EMBEDDERS_OPENGLUI_ANDROID_ANDROID_GRAPHICS_HANDLER_H_
#include <android_native_app_glue.h>
#include "embedders/openglui/common/gl_graphics_handler.h"
class AndroidGraphicsHandler : public GLGraphicsHandler {
public:
explicit AndroidGraphicsHandler(android_app* application);
int32_t Start();
void Stop();
private:
android_app* application_;
EGLDisplay display_;
EGLSurface surface_;
EGLContext context_;
};
#endif // EMBEDDERS_OPENGLUI_ANDROID_ANDROID_GRAPHICS_HANDLER_H_

View file

@ -0,0 +1,33 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_ANDROID_ANDROID_INPUT_HANDLER_H_
#define EMBEDDERS_OPENGLUI_ANDROID_ANDROID_INPUT_HANDLER_H_
#include "embedders/openglui/common/graphics_handler.h"
#include "embedders/openglui/common/input_handler.h"
class AndroidInputHandler : public InputHandler {
public:
AndroidInputHandler(VMGlue* vm_glue,
GraphicsHandler* graphics_handler)
: InputHandler(vm_glue),
graphics_handler_(graphics_handler) {
}
public:
int32_t Start() {
if (graphics_handler_->width() == 0 ||
graphics_handler_->height() == 0) {
return -1;
}
return 0;
}
private:
GraphicsHandler* graphics_handler_;
};
#endif // EMBEDDERS_OPENGLUI_ANDROID_ANDROID_INPUT_HANDLER_H_

View file

@ -0,0 +1,17 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_ANDROID_ANDROID_LOG_H_
#define EMBEDDERS_OPENGLUI_ANDROID_ANDROID_LOG_H_
#include <android/log.h>
#define LOGX(LOG_LEVEL, ...) do { \
__android_log_print(LOG_LEVEL, "DartExt", __VA_ARGS__); \
} while (0)
#define LOGI(...) LOGX(ANDROID_LOG_INFO, __VA_ARGS__)
#define LOGE(...) LOGX(ANDROID_LOG_ERROR, __VA_ARGS__)
#endif // EMBEDDERS_OPENGLUI_ANDROID_ANDROID_LOG_H_

View file

@ -0,0 +1,67 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_ANDROID_ANDROID_RESOURCE_H_
#define EMBEDDERS_OPENGLUI_ANDROID_ANDROID_RESOURCE_H_
#include <android_native_app_glue.h>
#include "embedders/openglui/common/log.h"
#include "embedders/openglui/common/resource.h"
class AndroidResource : public Resource {
public:
AndroidResource(android_app* application, const char* path)
: Resource(path),
asset_manager_(application->activity->assetManager),
asset_(NULL) {
}
int32_t descriptor() {
if (Open() == 0) {
descriptor_ = AAsset_openFileDescriptor(asset_, &start_, &length_);
LOGI("%s has start %d, length %d, fd %d",
path_, static_cast<int>(start_), static_cast<int>(length_),
descriptor_);
return descriptor_;
}
return -1;
}
off_t length() {
if (length_ < 0) {
length_ = AAsset_getLength(asset_);
}
return length_;
}
int32_t Open() {
LOGI("Attempting to open asset %s", path_);
asset_ = AAssetManager_open(asset_manager_, path_, AASSET_MODE_UNKNOWN);
if (asset_ != NULL) {
return 0;
}
LOGE("Could not open asset %s", path_);
return -1;
}
void Close() {
if (asset_ != NULL) {
AAsset_close(asset_);
asset_ = NULL;
}
}
int32_t Read(void* buffer, size_t count) {
size_t actual = AAsset_read(asset_, buffer, count);
return (actual == count) ? 0 : -1;
}
private:
AAssetManager* asset_manager_;
AAsset* asset_;
};
#endif // EMBEDDERS_OPENGLUI_ANDROID_ANDROID_RESOURCE_H_

View file

@ -0,0 +1,258 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "embedders/openglui/android/android_sound_handler.h"
#include "embedders/openglui/android/android_resource.h"
#include "embedders/openglui/common/log.h"
AndroidSoundHandler::AndroidSoundHandler(android_app* application)
: SoundHandler(),
application_(application),
engine_(NULL),
engine_if_(NULL),
output_mix_(NULL),
background_player_(NULL),
background_player_if_(NULL),
background_player_seek_if_(NULL),
sample_player_(NULL),
sample_player_if_(NULL),
sample_player_queue_(NULL) {
SoundHandler::instance_ = this;
}
int32_t AndroidSoundHandler::Start() {
LOGI("Starting SoundService");
const SLInterfaceID k_engine_mix_IIDs[] = { SL_IID_ENGINE };
const SLboolean k_engine_mix_reqs[] = { SL_BOOLEAN_TRUE };
const SLInterfaceID k_output_mix_IIDs[] = {};
const SLboolean k_output_mix_reqs[] = {};
int32_t res = slCreateEngine(&engine_, 0, NULL, 1,
k_engine_mix_IIDs, k_engine_mix_reqs);
if (res == SL_RESULT_SUCCESS) {
res = (*engine_)->Realize(engine_, SL_BOOLEAN_FALSE);
if (res == SL_RESULT_SUCCESS) {
res = (*engine_)->GetInterface(engine_, SL_IID_ENGINE, &engine_if_);
if (res == SL_RESULT_SUCCESS) {
res = (*engine_if_)->CreateOutputMix(engine_if_, &output_mix_, 0,
k_output_mix_IIDs, k_output_mix_reqs);
if (res == SL_RESULT_SUCCESS) {
res = (*output_mix_)->Realize(output_mix_, SL_BOOLEAN_FALSE);
if (res == SL_RESULT_SUCCESS) {
if (StartSamplePlayer() == 0) {
return 0;
}
}
}
}
}
}
LOGI("Failed to start SoundService");
Stop();
return -1;
}
void AndroidSoundHandler::Stop() {
StopBackground();
if (output_mix_ != NULL) {
(*output_mix_)->Destroy(output_mix_);
output_mix_ = NULL;
}
if (engine_ != NULL) {
(*engine_)->Destroy(engine_);
engine_ = NULL;
engine_if_ = NULL;
}
if (sample_player_ != NULL) {
(*sample_player_)->Destroy(sample_player_);
sample_player_ = NULL;
sample_player_if_ = NULL;
sample_player_queue_ = NULL;
}
samples_.clear();
}
int32_t AndroidSoundHandler::CreateAudioPlayer(SLEngineItf engine_if,
const SLInterfaceID extra_if,
SLDataSource data_source,
SLDataSink data_sink,
SLObjectItf& player_out,
SLPlayItf& player_if_out) {
const SLuint32 SoundPlayerIIDCount = 2;
const SLInterfaceID SoundPlayerIIDs[] = { SL_IID_PLAY, extra_if };
const SLboolean SoundPlayerReqs[] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
int32_t res = (*engine_if)->CreateAudioPlayer(engine_if,
&player_out,
&data_source,
&data_sink,
SoundPlayerIIDCount,
SoundPlayerIIDs,
SoundPlayerReqs);
if (res == SL_RESULT_SUCCESS) {
res = (*player_out)->Realize(player_out, SL_BOOLEAN_FALSE);
if (res == SL_RESULT_SUCCESS) {
res = (*player_out)->GetInterface(sample_player_,
SL_IID_PLAY,
&player_if_out);
if (res == SL_RESULT_SUCCESS) {
return 0;
}
}
}
return -1;
}
int32_t AndroidSoundHandler::PlayBackground(const char* path) {
LOGI("Creating audio player");
Resource resource(path);
int fd = resource.descriptor();
if (fd < 0) {
LOGI("Could not open file %s", path);
return -1;
}
SLDataLocator_AndroidFD data_locator_in = {
SL_DATALOCATOR_ANDROIDFD,
fd,
resource.start(),
resource.length()
};
SLDataFormat_MIME data_format = {
SL_DATAFORMAT_MIME,
NULL,
SL_CONTAINERTYPE_UNSPECIFIED
};
SLDataSource data_source = { &data_locator_in, &data_format };
resource.Close();
SLDataLocator_OutputMix data_locator_out =
{ SL_DATALOCATOR_OUTPUTMIX, output_mix_ };
SLDataSink data_sink = { &data_locator_out, NULL };
int32_t res = CreateAudioPlayer(engine_if_,
SL_IID_SEEK,
data_source,
data_sink,
background_player_,
background_player_if_);
if (res != SL_RESULT_SUCCESS) {
LOGE("Couldn't create audio player");
return -1;
}
if ((*background_player_)->
GetInterface(background_player_, SL_IID_SEEK,
&background_player_seek_if_) != SL_RESULT_SUCCESS) {
LOGE("Couldn't get seek interface");
return -1;
}
LOGI("Got seek interface");
if ((*background_player_seek_if_)->
SetLoop(background_player_seek_if_, SL_BOOLEAN_TRUE, 0,
SL_TIME_UNKNOWN) != SL_RESULT_SUCCESS) {
LOGE("Couldn't set loop");
return -1;
}
LOGI("Set loop");
if ((*background_player_if_)->
SetPlayState(background_player_if_, SL_PLAYSTATE_PLAYING) !=
SL_RESULT_SUCCESS) {
LOGE("Couldn't start playing");
return -1;
}
LOGI("Started playing");
return 0;
}
void AndroidSoundHandler::StopBackground() {
if (background_player_if_ != NULL) {
SLuint32 state;
(*background_player_)->GetState(background_player_, &state);
if (state == SL_OBJECT_STATE_REALIZED) {
(*background_player_if_)->SetPlayState(background_player_if_,
SL_PLAYSTATE_PAUSED);
(*background_player_)->Destroy(background_player_);
background_player_ = NULL;
background_player_if_ = NULL;
background_player_seek_if_ = NULL;
}
}
}
int32_t AndroidSoundHandler::StartSamplePlayer() {
SLDataLocator_AndroidSimpleBufferQueue data_locator_in = {
SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,
1
};
SLDataFormat_PCM data_format= {
SL_DATAFORMAT_PCM,
1,
SL_SAMPLINGRATE_44_1,
SL_PCMSAMPLEFORMAT_FIXED_16,
SL_PCMSAMPLEFORMAT_FIXED_16,
SL_SPEAKER_FRONT_CENTER,
SL_BYTEORDER_LITTLEENDIAN
};
SLDataSource data_source = { &data_locator_in, &data_format };
SLDataLocator_OutputMix data_locator_out =
{ SL_DATALOCATOR_OUTPUTMIX, output_mix_ };
SLDataSink data_sink = { &data_locator_out, NULL };
int32_t res = CreateAudioPlayer(engine_if_, SL_IID_BUFFERQUEUE,
data_source,
data_sink,
sample_player_, sample_player_if_);
if (res == SL_RESULT_SUCCESS) {
res = (*sample_player_)->GetInterface(sample_player_,
SL_IID_BUFFERQUEUE,
&sample_player_queue_);
if (res == SL_RESULT_SUCCESS) {
res = (*sample_player_if_)->SetPlayState(sample_player_if_,
SL_PLAYSTATE_PLAYING);
if (res == SL_RESULT_SUCCESS) {
return 0;
}
}
}
LOGE("Error while starting sample player");
return -1;
}
int32_t AndroidSoundHandler::PlaySample(const char* path) {
SLuint32 state;
(*sample_player_)->GetState(sample_player_, &state);
if (state != SL_OBJECT_STATE_REALIZED) {
LOGE("Sample player has not been realized");
} else {
Sample* sample = GetSample(path);
if (sample != NULL) {
int16_t* buffer = reinterpret_cast<int16_t*>(sample->buffer());
off_t len = sample->length();
// Remove any current sample.
int32_t res = (*sample_player_queue_)->Clear(sample_player_queue_);
if (res == SL_RESULT_SUCCESS) {
res = (*sample_player_queue_)->Enqueue(sample_player_queue_,
buffer, len);
if (res == SL_RESULT_SUCCESS) {
return 0;
}
LOGE("Enqueueing sample failed");
}
}
}
return -1;
}

View file

@ -0,0 +1,52 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_ANDROID_ANDROID_SOUND_HANDLER_H_
#define EMBEDDERS_OPENGLUI_ANDROID_ANDROID_SOUND_HANDLER_H_
#include <android_native_app_glue.h>
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include <SLES/OpenSLES_AndroidConfiguration.h>
#include <vector>
#include "embedders/openglui/common/sample.h"
#include "embedders/openglui/common/sound_handler.h"
#include "embedders/openglui/common/types.h"
class AndroidSoundHandler : public SoundHandler {
public:
explicit AndroidSoundHandler(android_app* application);
int32_t Start();
void Stop();
int32_t PlayBackground(const char* path);
void StopBackground();
int32_t PlaySample(const char* path);
private:
int32_t CreateAudioPlayer(SLEngineItf engine_if,
const SLInterfaceID extra_if,
SLDataSource data_source,
SLDataSink data_sink,
SLObjectItf& player_out,
SLPlayItf& player_if_out);
int32_t StartSamplePlayer();
android_app* application_;
SLObjectItf engine_;
SLEngineItf engine_if_;
SLObjectItf output_mix_;
SLObjectItf background_player_;
SLPlayItf background_player_if_;
SLSeekItf background_player_seek_if_;
SLObjectItf sample_player_;
SLPlayItf sample_player_if_;
SLBufferQueueItf sample_player_queue_;
};
#endif // EMBEDDERS_OPENGLUI_ANDROID_ANDROID_SOUND_HANDLER_H_

View file

@ -0,0 +1,238 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "embedders/openglui/android/eventloop.h"
#include "embedders/openglui/common/log.h"
EventLoop::EventLoop(android_app* application)
: enabled_(false),
quit_(false),
application_(application),
lifecycle_handler_(NULL),
input_handler_(NULL) {
application_->onAppCmd = ActivityCallback;
application_->onInputEvent = InputCallback;
application_->userData = this;
}
void EventLoop::Run(LifeCycleHandler* lifecycle_handler,
InputHandler* input_handler) {
int32_t result;
int32_t events;
android_poll_source* source;
lifecycle_handler_ = lifecycle_handler;
input_handler_ = input_handler;
LOGI("Starting event loop");
while (true) {
// If not enabled, block on events. If enabled, don't block
// so we can do useful work in onStep.
while ((result = ALooper_pollAll(enabled_ ? 0 : -1,
NULL,
&events,
reinterpret_cast<void**>(&source))) >= 0) {
if (source != NULL) {
source->process(application_, source);
}
if (application_->destroyRequested) {
return;
}
}
if (enabled_ && !quit_) {
LOGI("step");
if (lifecycle_handler_->OnStep() != 0) {
quit_ = true;
ANativeActivity_finish(application_->activity);
}
}
}
}
// Called when we gain focus.
void EventLoop::Activate() {
LOGI("activate");
if (!enabled_ && application_->window != NULL) {
quit_ = false;
enabled_ = true;
if (lifecycle_handler_->OnActivate() != 0) {
quit_ = true;
ANativeActivity_finish(application_->activity);
}
}
}
// Called when we lose focus.
void EventLoop::Deactivate() {
LOGI("deactivate");
if (enabled_) {
lifecycle_handler_->OnDeactivate();
enabled_ = false;
}
}
void EventLoop::ProcessActivityEvent(int32_t command) {
switch (command) {
case APP_CMD_CONFIG_CHANGED:
lifecycle_handler_->OnConfigurationChanged();
break;
case APP_CMD_INIT_WINDOW:
lifecycle_handler_->OnCreateWindow();
break;
case APP_CMD_DESTROY:
lifecycle_handler_->OnDestroy();
break;
case APP_CMD_GAINED_FOCUS:
Activate();
lifecycle_handler_->OnGainedFocus();
break;
case APP_CMD_LOST_FOCUS:
lifecycle_handler_->OnLostFocus();
Deactivate();
break;
case APP_CMD_LOW_MEMORY:
lifecycle_handler_->OnLowMemory();
break;
case APP_CMD_PAUSE:
lifecycle_handler_->OnPause();
Deactivate();
break;
case APP_CMD_RESUME:
lifecycle_handler_->OnResume();
break;
case APP_CMD_SAVE_STATE:
lifecycle_handler_->OnSaveState(&application_->savedState,
&application_->savedStateSize);
break;
case APP_CMD_START:
lifecycle_handler_->OnStart();
break;
case APP_CMD_STOP:
lifecycle_handler_->OnStop();
break;
case APP_CMD_TERM_WINDOW:
lifecycle_handler_->OnDestroyWindow();
Deactivate();
break;
default:
break;
}
}
bool EventLoop::OnTouchEvent(AInputEvent* event) {
int32_t type = AMotionEvent_getAction(event);
MotionEvent motion_event;
switch (type) {
case AMOTION_EVENT_ACTION_DOWN:
motion_event = kMotionDown;
break;
case AMOTION_EVENT_ACTION_UP:
motion_event = kMotionUp;
break;
case AMOTION_EVENT_ACTION_MOVE:
motion_event = kMotionMove;
break;
case AMOTION_EVENT_ACTION_CANCEL:
motion_event = kMotionCancel;
break;
case AMOTION_EVENT_ACTION_OUTSIDE:
motion_event = kMotionOutside;
break;
case AMOTION_EVENT_ACTION_POINTER_DOWN:
motion_event = kMotionPointerDown;
break;
case AMOTION_EVENT_ACTION_POINTER_UP:
motion_event = kMotionPointerUp;
break;
default:
return false;
}
// For now we just get the last coords.
float move_x = AMotionEvent_getX(event, 0);
float move_y = AMotionEvent_getY(event, 0);
int64_t when = AMotionEvent_getEventTime(event);
LOGI("Got motion event %d at %f, %f", type, move_x, move_y);
if (input_handler_->OnMotionEvent(motion_event, when, move_x, move_y) != 0) {
return false;
}
return true;
}
bool EventLoop::OnKeyEvent(AInputEvent* event) {
int32_t type = AKeyEvent_getAction(event);
KeyEvent key_event;
switch (type) {
case AKEY_EVENT_ACTION_DOWN:
key_event = kKeyDown;
break;
case AKEY_EVENT_ACTION_UP:
key_event = kKeyUp;
break;
case AKEY_EVENT_ACTION_MULTIPLE:
key_event = kKeyMultiple;
break;
default:
return false;
}
int32_t flags = AKeyEvent_getFlags(event);
/* Get the key code of the key event.
* This is the physical key that was pressed, not the Unicode character. */
int32_t key_code = AKeyEvent_getKeyCode(event);
/* Get the meta key state. */
int32_t meta_state = AKeyEvent_getMetaState(event);
/* Get the repeat count of the event.
* For both key up an key down events, this is the number of times the key
* has repeated with the first down starting at 0 and counting up from
* there. For multiple key events, this is the number of down/up pairs
* that have occurred. */
int32_t repeat = AKeyEvent_getRepeatCount(event);
/* Get the time of the most recent key down event, in the
* java.lang.System.nanoTime() time base. If this is a down event,
* this will be the same as eventTime.
* Note that when chording keys, this value is the down time of the most
* recently pressed key, which may not be the same physical key of this
* event. */
// TODO(gram): Use or remove this.
// int64_t key_down_time = AKeyEvent_getDownTime(event);
/* Get the time this event occurred, in the
* java.lang.System.nanoTime() time base. */
int64_t when = AKeyEvent_getEventTime(event);
LOGI("Got key event %d %d", type, key_code);
if (input_handler_->OnKeyEvent(key_event, when, flags, key_code,
meta_state, repeat) != 0) {
return false;
}
return true;
}
int32_t EventLoop::ProcessInputEvent(AInputEvent* event) {
int32_t event_type = AInputEvent_getType(event);
LOGI("Got input event type %d", event_type);
switch (event_type) {
case AINPUT_EVENT_TYPE_MOTION:
if (AInputEvent_getSource(event) == AINPUT_SOURCE_TOUCHSCREEN) {
return OnTouchEvent(event);
}
break;
case AINPUT_EVENT_TYPE_KEY:
return OnKeyEvent(event);
}
return 0;
}
void EventLoop::ActivityCallback(android_app* application, int32_t command) {
EventLoop* event_loop = reinterpret_cast<EventLoop*>(application->userData);
event_loop->ProcessActivityEvent(command);
}
int32_t EventLoop::InputCallback(android_app* application,
AInputEvent* event) {
EventLoop* event_loop = reinterpret_cast<EventLoop*>(application->userData);
return event_loop->ProcessInputEvent(event);
}

View file

@ -0,0 +1,39 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_ANDROID_EVENTLOOP_H_
#define EMBEDDERS_OPENGLUI_ANDROID_EVENTLOOP_H_
#include <android_native_app_glue.h>
#include "embedders/openglui/common/events.h"
#include "embedders/openglui/common/input_handler.h"
#include "embedders/openglui/common/lifecycle_handler.h"
class EventLoop {
public:
explicit EventLoop(android_app* application);
void Run(LifeCycleHandler* activity_handler,
InputHandler* input_handler);
protected:
void Activate();
void Deactivate();
void ProcessActivityEvent(int32_t command);
int32_t ProcessInputEvent(AInputEvent* event);
bool OnTouchEvent(AInputEvent* event);
bool OnKeyEvent(AInputEvent* event);
static void ActivityCallback(android_app* application, int32_t command);
static int32_t InputCallback(android_app* application, AInputEvent* event);
private:
bool enabled_;
bool quit_;
android_app* application_;
LifeCycleHandler* lifecycle_handler_;
InputHandler* input_handler_;
};
#endif // EMBEDDERS_OPENGLUI_ANDROID_EVENTLOOP_H_

View file

@ -0,0 +1,30 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "embedders/openglui/android/android_graphics_handler.h"
#include "embedders/openglui/android/android_input_handler.h"
#include "embedders/openglui/android/android_sound_handler.h"
#include "embedders/openglui/android/eventloop.h"
#include "embedders/openglui/common/context.h"
#include "embedders/openglui/common/dart_host.h"
#include "embedders/openglui/common/vm_glue.h"
void android_main(android_app* application) {
app_dummy(); // Link in native_app_glue.
AndroidGraphicsHandler graphics_handler(application);
VMGlue vm_glue(&graphics_handler, "/data/data/com.google.dartndk/app_dart");
AndroidInputHandler input_handler(&vm_glue, &graphics_handler);
AndroidSoundHandler sound_handler(application);
Timer timer;
Context app_context;
app_context.graphics_handler = &graphics_handler;
app_context.input_handler = &input_handler;
app_context.sound_handler = &sound_handler;
app_context.timer = &timer;
app_context.vm_glue = &vm_glue;
EventLoop eventLoop(application);
DartHost host(&app_context);
eventLoop.Run(&host, &input_handler);
}

View file

@ -0,0 +1,15 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Provide atexit, not part of Android libc or linker.
extern "C" int atexit(void (*function)(void)) {
// Return error code.
return 1;
}
// Provide __dso_handle, not part of Android libc or linker.
__attribute__((weak)) void *__dso_handle;

View file

@ -0,0 +1,23 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_COMMON_CONTEXT_H_
#define EMBEDDERS_OPENGLUI_COMMON_CONTEXT_H_
#include "embedders/openglui/common/graphics_handler.h"
#include "embedders/openglui/common/input_handler.h"
#include "embedders/openglui/common/sound_handler.h"
#include "embedders/openglui/common/timer.h"
#include "embedders/openglui/common/vm_glue.h"
struct Context {
GraphicsHandler* graphics_handler;
InputHandler* input_handler;
SoundHandler* sound_handler;
Timer* timer;
VMGlue* vm_glue;
};
#endif // EMBEDDERS_OPENGLUI_COMMON_CONTEXT_H_

View file

@ -0,0 +1,126 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "embedders/openglui/common/dart_host.h"
#include <math.h>
#include <unistd.h>
#include "embedders/openglui/common/log.h"
DartHost::DartHost(Context *context)
: graphics_handler_(context->graphics_handler),
input_handler_(context->input_handler),
sound_handler_(context->sound_handler),
timer_(context->timer),
vm_glue_(context->vm_glue),
active_(false) {
LOGI("Creating DartHost");
}
DartHost::~DartHost() {
LOGI("Freeing DartHost");
}
int32_t DartHost::OnActivate() {
return Activate();
}
int32_t DartHost::Activate() {
if (!active_) {
LOGI("Activating DartHost");
if (graphics_handler_->Start() != 0) {
return -1;
}
if (sound_handler_->Start() != 0) {
return -1;
}
if (input_handler_->Start() != 0) {
return -1;
}
timer_->reset();
LOGI("Starting main isolate");
int result = vm_glue_->StartMainIsolate();
if (result != 0) {
LOGE("startMainIsolate returned %d", result);
return -1;
}
active_ = true;
vm_glue_->CallSetup();
}
return 0;
}
void DartHost::OnDeactivate() {
Deactivate();
}
void DartHost::Deactivate() {
if (active_) {
active_ = false;
vm_glue_->FinishMainIsolate();
LOGI("Deactivating DartHost");
input_handler_->Stop();
sound_handler_->Stop();
graphics_handler_->Stop();
}
}
int32_t DartHost::OnStep() {
timer_->update();
vm_glue_->CallUpdate();
if (graphics_handler_->Update() != 0) {
return -1;
}
return 0;
}
void DartHost::OnStart() {
LOGI("Starting DartHost");
}
void DartHost::OnResume() {
LOGI("Resuming DartHost");
}
void DartHost::OnPause() {
LOGI("Pausing DartHost");
}
void DartHost::OnStop() {
LOGI("Stopping DartHost");
}
void DartHost::OnDestroy() {
LOGI("Destroying DartHost");
}
void DartHost::OnSaveState(void** data, size_t* size) {
LOGI("Saving DartHost state");
}
void DartHost::OnConfigurationChanged() {
LOGI("DartHost config changed");
}
void DartHost::OnLowMemory() {
LOGI("DartHost low on memory");
}
void DartHost::OnCreateWindow() {
LOGI("DartHost creating window");
}
void DartHost::OnDestroyWindow() {
LOGI("DartHost destroying window");
}
void DartHost::OnGainedFocus() {
LOGI("DartHost gained focus");
}
void DartHost::OnLostFocus() {
LOGI("DartHost lost focus");
}

View file

@ -0,0 +1,58 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_COMMON_DART_HOST_H_
#define EMBEDDERS_OPENGLUI_COMMON_DART_HOST_H_
#include "embedders/openglui/common/context.h"
#include "embedders/openglui/common/graphics_handler.h"
#include "embedders/openglui/common/input_handler.h"
#include "embedders/openglui/common/lifecycle_handler.h"
#include "embedders/openglui/common/sound_handler.h"
#include "embedders/openglui/common/timer.h"
#include "embedders/openglui/common/vm_glue.h"
#include "include/dart_api.h"
// Currently the life cycle management is very crude. We conservatively
// shutdown the main isolate when we lose focus and create a new one when
// we resume. This needs to be improved later when we understand this better,
// and we need some hooks to tell the Dart script to save/restore state
// (and an API that will support that).
class DartHost : public LifeCycleHandler {
public:
explicit DartHost(Context* context);
virtual ~DartHost();
void OnStart();
void OnResume();
void OnPause();
void OnStop();
void OnDestroy();
void OnSaveState(void** data, size_t* size);
void OnConfigurationChanged();
void OnLowMemory();
void OnCreateWindow();
void OnDestroyWindow();
void OnGainedFocus();
void OnLostFocus();
int32_t OnActivate();
void OnDeactivate();
int32_t OnStep();
private:
void Clear();
int32_t Activate();
void Deactivate();
GraphicsHandler* graphics_handler_;
InputHandler* input_handler_;
SoundHandler* sound_handler_;
Timer* timer_;
VMGlue* vm_glue_;
bool active_;
};
#endif // EMBEDDERS_OPENGLUI_COMMON_DART_HOST_H_

View file

@ -0,0 +1,39 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_COMMON_EVENTS_H_
#define EMBEDDERS_OPENGLUI_COMMON_EVENTS_H_
typedef enum {
kStart,
kStop,
kGainedFocus,
kLostFocus,
kPause,
kResume,
kSaveState,
kConfigChanged,
kInitWindow,
kTermWindow,
kDestroy
} LifecycleEvent;
typedef enum {
kKeyDown,
kKeyUp,
kKeyMultiple
} KeyEvent;
typedef enum {
kMotionDown,
kMotionUp,
kMotionMove,
kMotionCancel,
kMotionOutside,
kMotionPointerDown,
kMotionPointerUp
} MotionEvent;
#endif // EMBEDDERS_OPENGLUI_COMMON_EVENTS_H_

View file

@ -0,0 +1,993 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "embedders/openglui/common/extension.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "embedders/openglui/common/log.h"
#include "embedders/openglui/common/opengl.h"
#include "include/dart_api.h"
Dart_Handle HandleError(Dart_Handle handle) {
if (Dart_IsError(handle)) Dart_PropagateError(handle);
return handle;
}
void CheckGLError(const char *function) {
int error = glGetError();
if (error != GL_NO_ERROR) {
if (error == GL_INVALID_ENUM) {
LOGE("%s: An unacceptable value is given for an enumerated argument.",
function);
} else if (error == GL_INVALID_VALUE) {
LOGE("%s: A numeric argument is out of range.", function);
} else if (error == GL_INVALID_OPERATION) {
LOGE("%s: The specified operation is not allowed in the current state.",
function);
} else if (error == GL_INVALID_FRAMEBUFFER_OPERATION) {
LOGE("%s: The framebuffer object is not complete.", function);
} else if (error == GL_OUT_OF_MEMORY) {
LOGE("%s: There is not enough memory left to execute the command.",
function);
} else {
LOGE("ERROR!: %s returns %d", function, error);
}
}
}
const char* GetArgAsString(Dart_NativeArguments arguments, int idx) {
Dart_Handle whatHandle = HandleError(Dart_GetNativeArgument(arguments, idx));
uint8_t* str;
intptr_t length;
HandleError(Dart_StringLength(whatHandle, &length));
HandleError(Dart_StringToUTF8(whatHandle, &str, &length));
str[length] = 0;
return const_cast<const char*>(reinterpret_cast<char*>(str));
}
double GetArgAsDouble(Dart_NativeArguments arguments, int index) {
Dart_Handle handle = HandleError(Dart_GetNativeArgument(arguments, index));
if (Dart_IsDouble(handle)) {
double v;
HandleError(Dart_DoubleValue(handle, &v));
return v;
}
if (Dart_IsInteger(handle)) {
int64_t v;
HandleError(Dart_IntegerToInt64(handle, &v));
return static_cast<double>(v);
}
LOGE("Argument at index %d has non-numeric type", index);
Dart_ThrowException(Dart_NewStringFromCString("Numeric argument expected."));
return 0;
}
int64_t GetArgAsInt(Dart_NativeArguments arguments, int index) {
Dart_Handle handle = HandleError(Dart_GetNativeArgument(arguments, index));
if (Dart_IsDouble(handle)) {
double v;
HandleError(Dart_DoubleValue(handle, &v));
return static_cast<int64_t>(v);
}
if (Dart_IsInteger(handle)) {
int64_t v;
HandleError(Dart_IntegerToInt64(handle, &v));
return v;
}
LOGE("Argument at index %d has non-numeric type", index);
Dart_ThrowException(Dart_NewStringFromCString("Numeric argument expected."));
return 0;
}
bool GetArgAsBool(Dart_NativeArguments arguments, int index) {
Dart_Handle handle = HandleError(Dart_GetNativeArgument(arguments, index));
if (Dart_IsBoolean(handle)) {
bool v;
HandleError(Dart_BooleanValue(handle, &v));
return v;
}
LOGI("Argument at index %d has non-Boolean type", index);
Dart_ThrowException(Dart_NewStringFromCString("Boolean argument expected."));
return false;
}
GLint* GetArgsAsGLintList(Dart_NativeArguments arguments, int index,
int* len_out) {
Dart_Handle argHandle = HandleError(Dart_GetNativeArgument(arguments, index));
if (Dart_IsList(argHandle)) {
intptr_t len;
HandleError(Dart_ListLength(argHandle, &len));
GLint* list = new GLint[len];
for (int i = 0; i < len; i++) {
Dart_Handle vHandle = Dart_ListGetAt(argHandle, i);
int64_t v;
HandleError(Dart_IntegerToInt64(vHandle, &v));
list[i] = v;
}
*len_out = len;
return list;
}
LOGI("Argument at index %d has non-List type", index);
Dart_ThrowException(Dart_NewStringFromCString("List argument expected."));
return NULL;
}
GLfloat* GetArgsAsFloatList(Dart_NativeArguments arguments, int index,
int* len_out) {
Dart_Handle locationHandle =
HandleError(Dart_GetNativeArgument(arguments, 0));
int64_t location;
HandleError(Dart_IntegerToInt64(locationHandle, &location));
Dart_Handle argHandle = HandleError(Dart_GetNativeArgument(arguments, 1));
if (Dart_IsList(argHandle)) {
intptr_t len;
HandleError(Dart_ListLength(argHandle, &len));
GLfloat* list = new GLfloat[len];
for (int i = 0; i < len; i++) {
Dart_Handle vHandle = Dart_ListGetAt(argHandle, i);
double v;
HandleError(Dart_DoubleValue(vHandle, &v));
list[i] = v;
}
*len_out = len;
return list;
}
LOGI("Argument at index %d has non-List type", index);
Dart_ThrowException(Dart_NewStringFromCString("List argument expected."));
return NULL;
}
void SetBoolReturnValue(Dart_NativeArguments arguments, bool b) {
Dart_Handle result = HandleError(Dart_NewBoolean(b));
Dart_SetReturnValue(arguments, result);
}
void SetIntReturnValue(Dart_NativeArguments arguments, int v) {
Dart_Handle result = HandleError(Dart_NewInteger(v));
Dart_SetReturnValue(arguments, result);
}
void SetStringReturnValue(Dart_NativeArguments arguments, const char* s) {
Dart_Handle result = HandleError(Dart_NewStringFromCString(s));
Dart_SetReturnValue(arguments, result);
}
void Log(Dart_NativeArguments arguments) {
Dart_EnterScope();
LOGI("%s", GetArgAsString(arguments, 0));
Dart_ExitScope();
}
void LogError(Dart_NativeArguments arguments) {
Dart_EnterScope();
LOGE("%s", GetArgAsString(arguments, 0));
Dart_ExitScope();
}
void SystemRand(Dart_NativeArguments arguments) {
Dart_EnterScope();
SetIntReturnValue(arguments, rand());
Dart_ExitScope();
}
void SystemSrand(Dart_NativeArguments arguments) {
Dart_EnterScope();
bool success = false;
Dart_Handle seed_object = HandleError(Dart_GetNativeArgument(arguments, 0));
if (Dart_IsInteger(seed_object)) {
bool fits;
HandleError(Dart_IntegerFitsIntoInt64(seed_object, &fits));
if (fits) {
int64_t seed;
HandleError(Dart_IntegerToInt64(seed_object, &seed));
srand(static_cast<unsigned>(seed));
success = true;
}
}
SetBoolReturnValue(arguments, success);
Dart_ExitScope();
}
void SwapBuffers(Dart_NativeArguments arguments) {
LOGI("SwapBuffers");
Dart_EnterScope();
GLSwapBuffers();
CheckGLError("GLSwapBuffers");
Dart_ExitScope();
}
void GLAttachShader(Dart_NativeArguments arguments) {
LOGI("GLAttachShader");
Dart_EnterScope();
int64_t program = GetArgAsInt(arguments, 0);
int64_t shader = GetArgAsInt(arguments, 1);
glAttachShader(program, shader);
CheckGLError("glAttachShader");
Dart_ExitScope();
}
void GLBindBuffer(Dart_NativeArguments arguments) {
LOGI("GLBindBuffer");
Dart_EnterScope();
int64_t target = GetArgAsInt(arguments, 0);
int64_t buffer = GetArgAsInt(arguments, 1);
glBindBuffer(target, buffer);
CheckGLError("glBindBuffer");
Dart_ExitScope();
}
void GLBufferData(Dart_NativeArguments arguments) {
LOGI("GLBufferData");
Dart_EnterScope();
int64_t target = GetArgAsInt(arguments, 0);
Dart_Handle dataHandle = HandleError(Dart_GetNativeArgument(arguments, 1));
intptr_t size;
HandleError(Dart_ListLength(dataHandle, &size));
LOGI("Size: %d", static_cast<int>(size));
// TODO(vsm): No guarantee that this is a float!
float* data = new float[size];
for (int i = 0; i < size; i++) {
Dart_Handle elemHandle = HandleError(Dart_ListGetAt(dataHandle, i));
double value;
Dart_DoubleValue(elemHandle, &value);
data[i] = static_cast<float>(value);
LOGI("Value[%d]: %f", i, data[i]);
}
Dart_Handle usageHandle = HandleError(Dart_GetNativeArgument(arguments, 2));
int64_t usage;
HandleError(Dart_IntegerToInt64(usageHandle, &usage));
glBufferData(target, size * sizeof(data[0]), data, usage);
CheckGLError("glBufferData");
delete[] data;
Dart_ExitScope();
}
void GLCompileShader(Dart_NativeArguments arguments) {
LOGI("GLCompileShader");
Dart_EnterScope();
int64_t shader = GetArgAsInt(arguments, 0);
glCompileShader(shader);
CheckGLError("glCompileShader");
Dart_ExitScope();
}
void GLCreateBuffer(Dart_NativeArguments arguments) {
LOGI("GLCreateBuffer");
Dart_EnterScope();
GLuint buffer;
glGenBuffers(1, &buffer);
CheckGLError("glGenBuffers");
SetIntReturnValue(arguments, buffer);
Dart_ExitScope();
}
void GLCreateProgram(Dart_NativeArguments arguments) {
LOGI("GLCreateProgram");
Dart_EnterScope();
int64_t program = glCreateProgram();
CheckGLError("glCreateProgram");
SetIntReturnValue(arguments, program);
Dart_ExitScope();
}
void GLCreateShader(Dart_NativeArguments arguments) {
LOGI("GLCreateShader");
Dart_EnterScope();
int64_t type = GetArgAsInt(arguments, 0);
int64_t shader = glCreateShader((GLenum)type);
CheckGLError("glCreateShader");
SetIntReturnValue(arguments, shader);
Dart_ExitScope();
}
void GLDrawArrays(Dart_NativeArguments arguments) {
LOGI("GLDrawArrays");
Dart_EnterScope();
int64_t mode = GetArgAsInt(arguments, 0);
int64_t first = GetArgAsInt(arguments, 1);
int64_t count = GetArgAsInt(arguments, 2);
glDrawArrays(mode, first, count);
CheckGLError("glDrawArrays");
Dart_ExitScope();
LOGI("Done GLDrawArrays");
}
void GLEnableVertexAttribArray(Dart_NativeArguments arguments) {
LOGI("GLEnableVertexAttribArray");
Dart_EnterScope();
int64_t location = GetArgAsInt(arguments, 0);
glEnableVertexAttribArray(location);
CheckGLError("glEnableVertexAttribArray");
Dart_ExitScope();
}
void GLGetAttribLocation(Dart_NativeArguments arguments) {
LOGI("GLGetAttribLocation");
Dart_EnterScope();
int64_t program = GetArgAsInt(arguments, 0);
Dart_Handle nameHandle = HandleError(Dart_GetNativeArgument(arguments, 1));
intptr_t length;
HandleError(Dart_StringLength(nameHandle, &length));
uint8_t* str;
HandleError(Dart_StringToUTF8(nameHandle, &str, &length));
str[length] = 0;
int64_t location = glGetAttribLocation(program,
const_cast<const GLchar*>(reinterpret_cast<GLchar*>(str)));
CheckGLError("glGetAttribLocation");
SetIntReturnValue(arguments, location);
Dart_ExitScope();
}
void GLGetError(Dart_NativeArguments arguments) {
LOGI("GLGetError");
Dart_EnterScope();
SetIntReturnValue(arguments, glGetError());
Dart_ExitScope();
}
void GLGetProgramParameter(Dart_NativeArguments arguments) {
LOGI("GLGetProgramParameter");
Dart_EnterScope();
int64_t program = GetArgAsInt(arguments, 0);
int64_t param = GetArgAsInt(arguments, 1);
GLint value = -1;
glGetProgramiv(program, param, &value);
CheckGLError("glGetProgramiv");
SetIntReturnValue(arguments, value);
Dart_ExitScope();
}
void GLGetShaderParameter(Dart_NativeArguments arguments) {
LOGI("GLGetShaderParameter");
Dart_EnterScope();
int64_t shader = GetArgAsInt(arguments, 0);
int64_t param = GetArgAsInt(arguments, 1);
GLint value = -1;
glGetShaderiv((GLuint)shader, (GLenum)param, &value);
CheckGLError("glGetShaderiv");
SetIntReturnValue(arguments, value);
Dart_ExitScope();
}
void GLGetShaderInfoLog(Dart_NativeArguments arguments) {
LOGI("GLGetShaderInfoLog");
Dart_EnterScope();
int64_t shader = GetArgAsInt(arguments, 0);
GLint infoLogLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar* strInfoLog = new GLchar[infoLogLength + 1];
glGetShaderInfoLog(shader, infoLogLength, NULL, strInfoLog);
strInfoLog[infoLogLength] = 0;
SetStringReturnValue(arguments, strInfoLog);
Dart_ExitScope();
delete[] strInfoLog;
}
void GLGetProgramInfoLog(Dart_NativeArguments arguments) {
LOGI("GLGetProgramInfoLog");
Dart_EnterScope();
int64_t program = GetArgAsInt(arguments, 0);
GLint infoLogLength;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar* strInfoLog = new GLchar[infoLogLength + 1];
glGetProgramInfoLog(program, infoLogLength, NULL, strInfoLog);
strInfoLog[infoLogLength] = 0;
SetStringReturnValue(arguments, strInfoLog);
Dart_ExitScope();
delete[] strInfoLog;
}
void GLGetUniformLocation(Dart_NativeArguments arguments) {
LOGI("GLGetUniformLocation");
Dart_EnterScope();
int64_t program = GetArgAsInt(arguments, 0);
Dart_Handle nameHandle = HandleError(Dart_GetNativeArgument(arguments, 1));
intptr_t length;
HandleError(Dart_StringLength(nameHandle, &length));
uint8_t* str;
HandleError(Dart_StringToUTF8(nameHandle, &str, &length));
str[length] = 0;
int64_t location = glGetUniformLocation(program,
const_cast<const GLchar*>(reinterpret_cast<GLchar*>(str)));
CheckGLError("glGetUniformLocation");
SetIntReturnValue(arguments, location);
Dart_ExitScope();
}
void GLLinkProgram(Dart_NativeArguments arguments) {
LOGI("GLLinkProgram");
Dart_EnterScope();
int64_t program = GetArgAsInt(arguments, 0);
glLinkProgram(program);
CheckGLError("glLinkProgram");
Dart_ExitScope();
}
void GLShaderSource(Dart_NativeArguments arguments) {
LOGI("GLShaderSource");
Dart_EnterScope();
int64_t shader = GetArgAsInt(arguments, 0);
Dart_Handle sourceHandle = HandleError(Dart_GetNativeArgument(arguments, 1));
intptr_t length[1];
HandleError(Dart_StringLength(sourceHandle, length));
LOGI("Source length is %d", static_cast<int>(length[0]));
uint8_t* str[1];
HandleError(Dart_StringToUTF8(sourceHandle, &str[0], length));
LOGI("Converted length is %d", static_cast<int>(length[0]));
str[0][*length] = 0;
const GLchar* source =
const_cast<const GLchar*>(reinterpret_cast<GLchar*>(str[0]));
LOGI("Source: %s", source);
glShaderSource(shader, 1,
const_cast<const GLchar**>(reinterpret_cast<GLchar**>(str)), NULL);
CheckGLError("glShaderSource");
Dart_ExitScope();
}
void GLUseProgram(Dart_NativeArguments arguments) {
LOGI("GLUseProgram");
Dart_EnterScope();
int64_t program = GetArgAsInt(arguments, 0);
glUseProgram(program);
CheckGLError("glUseProgram");
Dart_ExitScope();
}
void GLUniform1i(Dart_NativeArguments arguments) {
LOGI("GLUniform1i");
Dart_EnterScope();
int64_t location = GetArgAsInt(arguments, 0);
int64_t v0 = GetArgAsInt(arguments, 1);
glUniform1i(location, v0);
CheckGLError("glUniform1i");
Dart_ExitScope();
}
void GLUniform2i(Dart_NativeArguments arguments) {
LOGI("GLUniform2i");
Dart_EnterScope();
int64_t location = GetArgAsInt(arguments, 0);
int64_t v0 = GetArgAsInt(arguments, 1);
int64_t v1 = GetArgAsInt(arguments, 2);
glUniform2i(location, v0, v1);
CheckGLError("glUniform2i");
Dart_ExitScope();
}
void GLUniform3i(Dart_NativeArguments arguments) {
LOGI("GLUniform3i");
Dart_EnterScope();
int64_t location = GetArgAsInt(arguments, 0);
int64_t v0 = GetArgAsInt(arguments, 1);
int64_t v1 = GetArgAsInt(arguments, 2);
int64_t v2 = GetArgAsInt(arguments, 3);
glUniform3i(location, v0, v1, v2);
CheckGLError("glUniform3i");
Dart_ExitScope();
}
void GLUniform4i(Dart_NativeArguments arguments) {
LOGI("GLUniform4i");
Dart_EnterScope();
int64_t location = GetArgAsInt(arguments, 0);
int64_t v0 = GetArgAsInt(arguments, 1);
int64_t v1 = GetArgAsInt(arguments, 2);
int64_t v2 = GetArgAsInt(arguments, 3);
int64_t v3 = GetArgAsInt(arguments, 4);
glUniform4i(location, v0, v1, v2, v3);
CheckGLError("glUniform4i");
Dart_ExitScope();
}
void GLUniform1f(Dart_NativeArguments arguments) {
LOGI("GLUniform1f");
Dart_EnterScope();
int64_t location = GetArgAsInt(arguments, 0);
double v0 = GetArgAsDouble(arguments, 1);
glUniform1f(location, v0);
CheckGLError("glUniform1f");
Dart_ExitScope();
}
void GLUniform2f(Dart_NativeArguments arguments) {
LOGI("GLUniform2f");
Dart_EnterScope();
int64_t location = GetArgAsInt(arguments, 0);
double v0 = GetArgAsDouble(arguments, 1);
double v1 = GetArgAsDouble(arguments, 2);
glUniform2f(location, v0, v1);
CheckGLError("glUniform2f");
Dart_ExitScope();
}
void GLUniform3f(Dart_NativeArguments arguments) {
LOGI("GLUniform3f");
Dart_EnterScope();
int64_t location = GetArgAsInt(arguments, 0);
double v0 = GetArgAsDouble(arguments, 1);
double v1 = GetArgAsDouble(arguments, 2);
double v2 = GetArgAsDouble(arguments, 3);
glUniform3f(location, v0, v1, v2);
CheckGLError("glUniform3f");
Dart_ExitScope();
}
void GLUniform4f(Dart_NativeArguments arguments) {
LOGI("GLUniform4f");
Dart_EnterScope();
int64_t location = GetArgAsInt(arguments, 0);
double v0 = GetArgAsDouble(arguments, 1);
double v1 = GetArgAsDouble(arguments, 2);
double v2 = GetArgAsDouble(arguments, 3);
double v3 = GetArgAsDouble(arguments, 4);
glUniform4f(location, v0, v1, v2, v3);
CheckGLError("glUniform4f");
Dart_ExitScope();
}
void GLUniform1iv(Dart_NativeArguments arguments) {
LOGI("GLUniform1iv");
Dart_EnterScope();
int64_t location = GetArgAsInt(arguments, 0);
int len;
GLint* list = GetArgsAsGLintList(arguments, 1, &len);
if (list != NULL) {
glUniform1iv(location, len, list);
delete [] list;
CheckGLError("glUniform1iv");
}
Dart_ExitScope();
}
void GLUniform2iv(Dart_NativeArguments arguments) {
LOGI("GLUniform2iv");
Dart_EnterScope();
int64_t location = GetArgAsInt(arguments, 0);
int len;
GLint* list = GetArgsAsGLintList(arguments, 1, &len);
if (list != NULL) {
glUniform2iv(location, len / 2, list);
delete [] list;
CheckGLError("glUniform2iv");
}
Dart_ExitScope();
}
void GLUniform3iv(Dart_NativeArguments arguments) {
LOGI("GLUniform3iv");
Dart_EnterScope();
int64_t location = GetArgAsInt(arguments, 0);
int len;
GLint* list = GetArgsAsGLintList(arguments, 1, &len);
if (list != NULL) {
glUniform3iv(location, len / 3, list);
delete [] list;
CheckGLError("glUniform3iv");
}
Dart_ExitScope();
}
void GLUniform4iv(Dart_NativeArguments arguments) {
LOGI("GLUniform4iv");
Dart_EnterScope();
int64_t location = GetArgAsInt(arguments, 0);
int len;
GLint* list = GetArgsAsGLintList(arguments, 1, &len);
if (list != NULL) {
glUniform1iv(location, len / 4, list);
delete [] list;
CheckGLError("glUniform4iv");
}
Dart_ExitScope();
}
void GLUniform1fv(Dart_NativeArguments arguments) {
LOGI("GLUniform1fv");
Dart_EnterScope();
int64_t location = GetArgAsInt(arguments, 0);
int len;
GLfloat* list = GetArgsAsFloatList(arguments, 1, &len);
if (list != NULL) {
glUniform1fv(location, len, list);
delete [] list;
CheckGLError("glUniform1fv");
}
Dart_ExitScope();
}
void GLUniform2fv(Dart_NativeArguments arguments) {
LOGI("GLUniform2fv");
Dart_EnterScope();
int64_t location = GetArgAsInt(arguments, 0);
int len;
GLfloat* list = GetArgsAsFloatList(arguments, 1, &len);
if (list != NULL) {
glUniform2fv(location, len / 2, list);
delete [] list;
CheckGLError("glUniform2fv");
}
Dart_ExitScope();
}
void GLUniform3fv(Dart_NativeArguments arguments) {
LOGI("GLUniform3fv");
Dart_EnterScope();
int64_t location = GetArgAsInt(arguments, 0);
int len;
GLfloat* list = GetArgsAsFloatList(arguments, 1, &len);
if (list != NULL) {
glUniform3fv(location, len / 3, list);
delete [] list;
CheckGLError("glUniform3fv");
}
Dart_ExitScope();
}
void GLUniform4fv(Dart_NativeArguments arguments) {
LOGI("In GLUniform4fv");
Dart_EnterScope();
int64_t location = GetArgAsInt(arguments, 0);
int len;
GLfloat* list = GetArgsAsFloatList(arguments, 1, &len);
if (list != NULL) {
glUniform4fv(location, len / 4, list);
delete [] list;
CheckGLError("glUniform4fv");
}
Dart_ExitScope();
}
void GLViewport(Dart_NativeArguments arguments) {
LOGI("GLViewport");
Dart_EnterScope();
int64_t x = GetArgAsInt(arguments, 0);
int64_t y = GetArgAsInt(arguments, 1);
int64_t width = GetArgAsInt(arguments, 2);
int64_t height = GetArgAsInt(arguments, 3);
glViewport(x, y, width, height);
CheckGLError("glViewPort");
Dart_ExitScope();
}
void GLVertexAttribPointer(Dart_NativeArguments arguments) {
LOGI("GLVertexAttribPointer");
Dart_EnterScope();
int64_t index = GetArgAsInt(arguments, 0);
int64_t size = GetArgAsInt(arguments, 1);
int64_t type = GetArgAsInt(arguments, 2);
bool normalized = GetArgAsBool(arguments, 3);
int64_t stride = GetArgAsInt(arguments, 4);
Dart_Handle pointerHandle = HandleError(Dart_GetNativeArgument(arguments, 5));
int64_t pointerValue;
HandleError(Dart_IntegerToInt64(pointerHandle, &pointerValue));
const void* pointer;
pointer = const_cast<const void*>(reinterpret_cast<void*>(pointerValue));
glVertexAttribPointer(index, size, type, normalized, stride, pointer);
CheckGLError("glVertexAttribPointer");
Dart_ExitScope();
}
void GLClearColor(Dart_NativeArguments arguments) {
LOGI("GLClearColor");
Dart_EnterScope();
double red = GetArgAsDouble(arguments, 0);
double green = GetArgAsDouble(arguments, 1);
double blue = GetArgAsDouble(arguments, 2);
double alpha = GetArgAsDouble(arguments, 3);
glClearColor(red, green, blue, alpha);
CheckGLError("glClearColor");
Dart_ExitScope();
}
void GLClearDepth(Dart_NativeArguments arguments) {
LOGI("GLClearDepth");
Dart_EnterScope();
double depth = GetArgAsDouble(arguments, 0);
#if defined(__ANDROID__)
glClearDepthf(depth);
#else
glClearDepth(depth);
#endif
CheckGLError("glClearDepth");
Dart_ExitScope();
}
void GLClear(Dart_NativeArguments arguments) {
LOGI("GLClear");
Dart_EnterScope();
Dart_Handle maskHandle = HandleError(Dart_GetNativeArgument(arguments, 0));
int64_t mask;
HandleError(Dart_IntegerToInt64(maskHandle, &mask));
glClear(mask);
CheckGLError("glClear");
Dart_ExitScope();
}
void ReturnGLIntConstant(Dart_NativeArguments arguments, int c) {
Dart_EnterScope();
SetIntReturnValue(arguments, c);
Dart_ExitScope();
}
void GLArrayBuffer(Dart_NativeArguments arguments) {
ReturnGLIntConstant(arguments, GL_ARRAY_BUFFER);
}
void GLColorBufferBit(Dart_NativeArguments arguments) {
ReturnGLIntConstant(arguments, GL_COLOR_BUFFER_BIT);
}
void GLCompileStatus(Dart_NativeArguments arguments) {
ReturnGLIntConstant(arguments, GL_COMPILE_STATUS);
}
void GLDeleteStatus(Dart_NativeArguments arguments) {
ReturnGLIntConstant(arguments, GL_DELETE_STATUS);
}
void GLDepthBufferBit(Dart_NativeArguments arguments) {
ReturnGLIntConstant(arguments, GL_DEPTH_BUFFER_BIT);
}
void GLFloat(Dart_NativeArguments arguments) {
ReturnGLIntConstant(arguments, GL_FLOAT);
}
void GLFragmentShader(Dart_NativeArguments arguments) {
ReturnGLIntConstant(arguments, GL_FRAGMENT_SHADER);
}
void GLLinkStatus(Dart_NativeArguments arguments) {
ReturnGLIntConstant(arguments, GL_LINK_STATUS);
}
void GLStaticDraw(Dart_NativeArguments arguments) {
ReturnGLIntConstant(arguments, GL_STATIC_DRAW);
}
void GLTriangleStrip(Dart_NativeArguments arguments) {
ReturnGLIntConstant(arguments, GL_TRIANGLE_STRIP);
}
void GLTriangles(Dart_NativeArguments arguments) {
ReturnGLIntConstant(arguments, GL_TRIANGLES);
}
void GLTrue(Dart_NativeArguments arguments) {
ReturnGLIntConstant(arguments, GL_TRUE);
}
void GLValidateStatus(Dart_NativeArguments arguments) {
ReturnGLIntConstant(arguments, GL_VALIDATE_STATUS);
}
void GLVertexShader(Dart_NativeArguments arguments) {
ReturnGLIntConstant(arguments, GL_VERTEX_SHADER);
}
uint8_t* RandomArray(int seed, int length) {
if (length <= 0 || length > 10000000) return NULL;
uint8_t* values = reinterpret_cast<uint8_t*>(malloc(length));
if (NULL == values) return NULL;
srand(seed);
for (int i = 0; i < length; ++i) {
values[i] = rand() % 256;
}
return values;
}
void WrappedRandomArray(Dart_Port dest_port_id,
Dart_Port reply_port_id,
Dart_CObject* message) {
if (message->type == Dart_CObject::kArray &&
2 == message->value.as_array.length) {
// Use .as_array and .as_int32 to access the data in the Dart_CObject.
Dart_CObject* param0 = message->value.as_array.values[0];
Dart_CObject* param1 = message->value.as_array.values[1];
if (param0->type == Dart_CObject::kInt32 &&
param1->type == Dart_CObject::kInt32) {
int length = param0->value.as_int32;
int seed = param1->value.as_int32;
uint8_t* values = RandomArray(seed, length);
if (values != NULL) {
Dart_CObject result;
result.type = Dart_CObject::kUint8Array;
result.value.as_byte_array.values = values;
result.value.as_byte_array.length = length;
Dart_PostCObject(reply_port_id, &result);
free(values);
// It is OK that result is destroyed when function exits.
// Dart_PostCObject has copied its data.
return;
}
}
}
Dart_CObject result;
result.type = Dart_CObject::kNull;
Dart_PostCObject(reply_port_id, &result);
}
void RandomArrayServicePort(Dart_NativeArguments arguments) {
Dart_EnterScope();
Dart_SetReturnValue(arguments, Dart_Null());
Dart_Port service_port =
Dart_NewNativePort("RandomArrayService", WrappedRandomArray, true);
if (service_port != ((Dart_Port)0)) {
Dart_Handle send_port = HandleError(Dart_NewSendPort(service_port));
Dart_SetReturnValue(arguments, send_port);
}
Dart_ExitScope();
}
void PlayBackground(Dart_NativeArguments arguments) {
LOGI("PlayBackground");
Dart_EnterScope();
const char* what = GetArgAsString(arguments, 0);
int rtn = PlayBackgroundSound(what);
SetIntReturnValue(arguments, rtn);
Dart_ExitScope();
}
void StopBackground(Dart_NativeArguments arguments) {
LOGI("StopBackground");
Dart_EnterScope();
StopBackgroundSound();
Dart_ExitScope();
}
void LoadSample(Dart_NativeArguments arguments) {
LOGI("LoadSample");
Dart_EnterScope();
const char* what = GetArgAsString(arguments, 0);
int rtn = LoadSoundSample(what);
SetIntReturnValue(arguments, rtn);
Dart_ExitScope();
}
void PlaySample(Dart_NativeArguments arguments) {
LOGI("PlaySample");
Dart_EnterScope();
const char* what = GetArgAsString(arguments, 0);
int rtn = PlaySoundSample(what);
SetIntReturnValue(arguments, rtn);
Dart_ExitScope();
}
struct FunctionLookup {
const char* name;
Dart_NativeFunction function;
};
FunctionLookup function_list[] = {
{"Log", Log},
{"LogError", LogError},
{"SystemRand", SystemRand},
{"SystemSrand", SystemSrand},
{"SwapBuffers", SwapBuffers},
{"GLAttachShader", GLAttachShader},
{"GLBindBuffer", GLBindBuffer},
{"GLBufferData", GLBufferData},
{"GLClear", GLClear},
{"GLClearColor", GLClearColor},
{"GLClearDepth", GLClearDepth},
{"GLCompileShader", GLCompileShader},
{"GLCreateBuffer", GLCreateBuffer},
{"GLCreateProgram", GLCreateProgram},
{"GLCreateShader", GLCreateShader},
{"GLDrawArrays", GLDrawArrays},
{"GLEnableVertexAttribArray", GLEnableVertexAttribArray},
{"GLGetAttribLocation", GLGetAttribLocation},
{"GLGetError", GLGetError},
{"GLGetProgramParameter", GLGetProgramParameter},
{"GLGetShaderParameter", GLGetShaderParameter},
{"GLGetUniformLocation", GLGetUniformLocation},
{"GLLinkProgram", GLLinkProgram},
{"GLShaderSource", GLShaderSource},
{"GLUniform1f", GLUniform1f},
{"GLUniform2f", GLUniform2f},
{"GLUniform3f", GLUniform3f},
{"GLUniform4f", GLUniform4f},
{"GLUniform1i", GLUniform1i},
{"GLUniform2i", GLUniform2i},
{"GLUniform3i", GLUniform3i},
{"GLUniform4i", GLUniform4i},
{"GLUniform1fv", GLUniform1fv},
{"GLUniform2fv", GLUniform2fv},
{"GLUniform3fv", GLUniform3fv},
{"GLUniform4fv", GLUniform4fv},
{"GLUniform1iv", GLUniform1iv},
{"GLUniform2iv", GLUniform2iv},
{"GLUniform3iv", GLUniform3iv},
{"GLUniform4iv", GLUniform4iv},
{"GLUseProgram", GLUseProgram},
{"GLVertexAttribPointer", GLVertexAttribPointer},
{"GLViewport", GLViewport},
{"GLArrayBuffer", GLArrayBuffer},
{"GLColorBufferBit", GLColorBufferBit},
{"GLCompileStatus", GLCompileStatus},
{"GLDeleteStatus", GLDeleteStatus},
{"GLDepthBufferBit", GLDepthBufferBit},
{"GLFloat", GLFloat},
{"GLFragmentShader", GLFragmentShader},
{"GLLinkStatus", GLLinkStatus},
{"GLTriangleStrip", GLTriangleStrip},
{"GLTriangles", GLTriangles},
{"GLTrue", GLTrue},
{"GLStaticDraw", GLStaticDraw},
{"GLValidateStatus", GLValidateStatus},
{"GLVertexShader", GLVertexShader},
{"GLGetShaderInfoLog", GLGetShaderInfoLog},
{"GLGetProgramInfoLog", GLGetProgramInfoLog},
{"RandomArray_ServicePort", RandomArrayServicePort},
// Audio support.
{"PlayBackground", PlayBackground},
{"StopBackground", StopBackground},
{"LoadSample", LoadSample},
{"PlaySample", PlaySample},
{NULL, NULL}};
Dart_NativeFunction ResolveName(Dart_Handle name, int argc) {
if (!Dart_IsString(name)) return NULL;
Dart_NativeFunction result = NULL;
Dart_EnterScope();
const char* cname;
HandleError(Dart_StringToCString(name, &cname));
for (int i = 0; function_list[i].name != NULL; ++i) {
if (strcmp(function_list[i].name, cname) == 0) {
result = function_list[i].function;
break;
}
}
Dart_ExitScope();
return result;
}

View file

@ -0,0 +1,18 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_COMMON_EXTENSION_H_
#define EMBEDDERS_OPENGLUI_COMMON_EXTENSION_H_
#include "include/dart_api.h"
Dart_NativeFunction ResolveName(Dart_Handle name, int argc);
extern int32_t PlayBackgroundSound(const char* path);
extern void StopBackgroundSound();
extern int32_t LoadSoundSample(const char* path);
extern int32_t PlaySoundSample(const char* path);
#endif // EMBEDDERS_OPENGLUI_COMMON_EXTENSION_H_

View file

@ -0,0 +1,186 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library android_extension;
// The simplest way to call native code: top-level functions.
int systemRand() native "SystemRand";
void systemSrand(int seed) native "SystemSrand";
void log(String what) native "Log";
// EGL functions.
void glSwapBuffers() native "SwapBuffers";
// GL functions.
void glAttachShader(int program, int shader) native "GLAttachShader";
void glBindBuffer(int target, int buffer) native "GLBindBuffer";
void glBufferData(int target, List data, int usage) native "GLBufferData";
void glClearColor(num r, num g, num b, num alpha) native "GLClearColor";
void glClearDepth(num depth) native "GLClearDepth";
void glClear(int mask) native "GLClear";
void glCompileShader(int shader) native "GLCompileShader";
int glCreateBuffer() native "GLCreateBuffer";
int glCreateProgram() native "GLCreateProgram";
int glCreateShader(int shaderType) native "GLCreateShader";
void glDrawArrays(int mode, int first, int count) native "GLDrawArrays";
void glEnableVertexAttribArray(int index) native "GLEnableVertexAttribArray";
int glGetAttribLocation(int program, String name) native "GLGetAttribLocation";
int glGetError() native "GLGetError";
int glGetProgramParameter(int program, int param)
native "GLGetProgramParameter";
int glGetShaderParameter(int shader, int param) native "GLGetShaderParameter";
int glGetUniformLocation(int program, String name)
native "GLGetUniformLocation";
void glLinkProgram(int program) native "GLLinkProgram";
void glShaderSource(int shader, String source) native "GLShaderSource";
void glUniform1f(int location, double v0) native "GLUniform1f";
void glUniform2f(int location, double v0, double v1) native "GLUniform2f";
void glUniform3f(int location, double v0, double v1, double v2)
native "GLUniform3f";
void glUniform4f(int location, double v0, double v1, double v2, double v3)
native "GLUniform4f";
void glUniform1i(int location, int v0) native "GLUniform1i";
void glUniform2i(int location, int v0, int v1) native "GLUniform2i";
void glUniform3i(int location, int v0, int v1, int v2) native "GLUniform3i";
void glUniform4i(int location, int v0, int v1, int v2, int v3)
native "GLUniform4i";
void glUniform1fv(int location, List values) native "GLUniform1fv";
void glUniform2fv(int location, List values) native "GLUniform2fv";
void glUniform3fv(int location, List values) native "GLUniform3fv";
void glUniform4fv(int location, List values) native "GLUniform4fv";
void glUniform1iv(int location, List values) native "GLUniform1iv";
void glUniform2iv(int location, List values) native "GLUniform2iv";
void glUniform3iv(int location, List values) native "GLUniform3iv";
void glUniform4iv(int location, List values) native "GLUniform4iv";
void glUseProgram(int program) native "GLUseProgram";
void glVertexAttribPointer(int index, int size, int type, bool normalized,
int stride, int pointer) native "GLVertexAttribPointer";
void glViewport(int x, int y, int width, int height) native "GLViewport";
int glArrayBuffer() native "GLArrayBuffer";
int glColorBufferBit() native "GLColorBufferBit";
int glCompileStatus() native "GLCompileStatus";
int glDeleteStatus() native "GLDeleteStatus";
int glDepthBufferBit() native "GLDepthBufferBit";
int glFloat() native "GLFloat";
int glFragmentShader() native "GLFragmentShader";
int glLinkStatus() native "GLLinkStatus";
int glStaticDraw() native "GLStaticDraw";
int glTriangleStrip() native "GLTriangleStrip";
int glTriangles() native "GLTriangles";
int glTrue() native "GLTrue";
int glValidateStatus() native "GLValidateStatus";
int glVertexShader() native "GLVertexShader";
String glGetShaderInfoLog(int shader) native "GLGetShaderInfoLog";
String glGetProgramInfoLog(int program) native "GLGetProgramInfoLog";
class WebGLRenderingContext {
WebGLRenderingContext();
static get ARRAY_BUFFER => glArrayBuffer();
static get COLOR_BUFFER_BIT => glColorBufferBit();
static get COMPILE_STATUS => glCompileStatus();
static get DELETE_STATUS => glDeleteStatus();
static get DEPTH_BUFFER_BIT => glDepthBufferBit();
static get FLOAT => glFloat();
static get FRAGMENT_SHADER => glFragmentShader();
static get LINK_STATUS => glLinkStatus();
static get STATIC_DRAW => glStaticDraw();
static get TRUE => glTrue();
static get TRIANGLE_STRIP => glTriangleStrip();
static get TRIANGLES => glTriangles();
static get VALIDATE_STATUS => glValidateStatus();
static get VERTEX_SHADER => glVertexShader();
attachShader(program, shader) => glAttachShader(program, shader);
bindBuffer(target, buffer) => glBindBuffer(target, buffer);
bufferData(target, data, usage) => glBufferData(target, data, usage);
clearColor(r, g, b, alpha) => glClearColor(r, g, b, alpha);
clearDepth(depth) => glClearDepth(depth);
clear(mask) => glClear(mask);
compileShader(shader) => glCompileShader(shader);
createBuffer() => glCreateBuffer();
createProgram() => glCreateProgram();
createShader(shaderType) => glCreateShader(shaderType);
drawArrays(mode, first, count) => glDrawArrays(mode, first, count);
enableVertexAttribArray(index) => glEnableVertexAttribArray(index);
getAttribLocation(program, name) => glGetAttribLocation(program, name);
getError() => glGetError();
getProgramParameter(program, name) {
var rtn = glGetProgramParameter(program, name);
if (name == DELETE_STATUS ||
name == LINK_STATUS ||
name == VALIDATE_STATUS) {
return (rtn == 0) ? false : true;
}
return rtn;
}
getShaderParameter(shader, name) {
var rtn = glGetShaderParameter(shader, name);
if (name == DELETE_STATUS || name == COMPILE_STATUS) {
return (rtn == 0) ? false : true;
}
return rtn;
}
getUniformLocation(program, name) => glGetUniformLocation(program, name);
linkProgram(program) => glLinkProgram(program);
shaderSource(shader, source) => glShaderSource(shader, source);
uniform1f(location, v0) => glUniform1f(location, v0);
uniform2f(location, v0, v1) => glUniform2f(location, v0, v1);
uniform3f(location, v0, v1, v2) => glUniform3f(location, v0, v1, v2);
uniform4f(location, v0, v1, v2, v3) => glUniform4f(location, v0, v1, v2, v3);
uniform1i(location, v0) => glUniform1i(location, v0);
uniform2i(location, v0, v1) => glUniform2i(location, v0, v1);
uniform3i(location, v0, v1, v2) => glUniform3i(location, v0, v1, v2);
uniform4i(location, v0, v1, v2, v3) => glUniform4i(location, v0, v1, v2, v3);
uniform1fv(location, values) => glUniform1fv(location, values);
uniform2fv(location, values) => glUniform2fv(location, values);
uniform3fv(location, values) => glUniform3fv(location, values);
uniform4fv(location, values) => glUniform4fv(location, values);
uniform1iv(location, values) => glUniform1iv(location, values);
uniform2iv(location, values) => glUniform2iv(location, values);
uniform3iv(location, values) => glUniform3iv(location, values);
uniform4iv(location, values) => glUniform4iv(location, values);
useProgram(program) => glUseProgram(program);
vertexAttribPointer(index, size, type, normalized, stride, pointer) =>
glVertexAttribPointer(index, size, type, normalized, stride, pointer);
viewport(x, y, width, height) => glViewport(x, y, width, height);
getShaderInfoLog(shader) => glGetShaderInfoLog(shader);
getProgramInfoLog(program) => glGetProgramInfoLog(program);
// TODO(vsm): Kill.
noSuchMethod(invocation) {
throw new Exception('Unimplemented ${invocation.memberName}');
}
}
var gl = new WebGLRenderingContext();
//------------------------------------------------------------------
// Simple audio support.
void playBackground(String path) native "PlayBackground";
void stopBackground() native "StopBackground";
//-------------------------------------------------------------------
// Set up print().
get _printClosure => (s) {
try {
log(s);
} catch (_) {
throw(s);
}
};
//------------------------------------------------------------------
// Temp hack for compat with WebGL.
class Float32Array extends List<double> {
Float32Array.fromList(List a) {
addAll(a);
}
}

View file

@ -0,0 +1,64 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "embedders/openglui/common/gl_graphics_handler.h"
#include "embedders/openglui/common/log.h"
extern void CheckGLError(const char *function);
void GLGraphicsHandler::SetViewport(int left, int top, int width, int height) {
glViewport(left, top, width, height);
CheckGLError("glViewPort");
}
int GLGraphicsHandler::BuildProgram(const char* vertexShaderSource,
const char* fragmentShaderSource) const {
int vertexShader = BuildShader(vertexShaderSource, GL_VERTEX_SHADER);
int fragmentShader = BuildShader(fragmentShaderSource, GL_FRAGMENT_SHADER);
if (vertexShader < 0 || fragmentShader < 0) {
return -1;
}
GLuint programHandle = glCreateProgram();
glAttachShader(programHandle, static_cast<GLuint>(vertexShader));
glAttachShader(programHandle, static_cast<GLuint>(fragmentShader));
glLinkProgram(programHandle);
GLint linkSuccess;
glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
if (linkSuccess == GL_FALSE) {
GLint infoLogLength;
glGetProgramiv(programHandle, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar* strInfoLog = new GLchar[infoLogLength + 1];
glGetProgramInfoLog(programHandle, infoLogLength, NULL, strInfoLog);
strInfoLog[infoLogLength] = 0;
LOGE("Link failed: %s", strInfoLog);
delete[] strInfoLog;
return -1;
}
return static_cast<int>(programHandle);
}
int GLGraphicsHandler::BuildShader(const char* source,
GLenum shaderType) const {
GLuint shaderHandle = glCreateShader(shaderType);
glShaderSource(shaderHandle, 1, &source, NULL);
glCompileShader(shaderHandle);
GLint compileSuccess;
glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
if (compileSuccess == GL_FALSE) {
GLint infoLogLength = 0;
glGetShaderiv(shaderHandle, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar* strInfoLog = new GLchar[infoLogLength + 1];
glGetShaderInfoLog(shaderHandle, infoLogLength, NULL, strInfoLog);
strInfoLog[infoLogLength] = 0;
LOGE("Shader compile failed: %s", strInfoLog);
delete [] strInfoLog;
return -1;
}
return static_cast<int>(shaderHandle);
}

View file

@ -0,0 +1,40 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_COMMON_GL_GRAPHICS_HANDLER_H_
#define EMBEDDERS_OPENGLUI_COMMON_GL_GRAPHICS_HANDLER_H_
#include "embedders/openglui/common/graphics_handler.h"
#include "embedders/openglui/common/opengl.h"
#include "embedders/openglui/common/timer.h"
class GLGraphicsHandler : public GraphicsHandler {
public:
GLGraphicsHandler()
: GraphicsHandler() {
}
virtual int32_t Start() = 0;
virtual void Stop() = 0;
void SwapBuffers() {
GLSwapBuffers();
}
virtual int32_t Update() {
SwapBuffers();
return 0;
}
void SetViewport(int left, int top, int width, int height);
int BuildProgram(const char* vertexShaderSource,
const char* fragmentShaderSource) const;
int BuildShader(const char* source, GLenum shaderType) const;
virtual ~GLGraphicsHandler() {
}
};
#endif // EMBEDDERS_OPENGLUI_COMMON_GL_GRAPHICS_HANDLER_H_

View file

@ -0,0 +1,47 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_COMMON_GRAPHICS_HANDLER_H_
#define EMBEDDERS_OPENGLUI_COMMON_GRAPHICS_HANDLER_H_
#include <stdint.h>
#include "embedders/openglui/common/isized.h"
#include "embedders/openglui/common/timer.h"
class GraphicsHandler : public ISized {
public:
GraphicsHandler()
: width_(0),
height_(0) {
}
const int32_t& height() {
return height_;
}
const int32_t& width() {
return width_;
}
virtual int32_t Start() = 0;
virtual void Stop() = 0;
virtual void SwapBuffers() = 0;
virtual int32_t Update() {
return 0;
}
virtual void SetViewport(int left, int top, int width, int height) = 0;
virtual ~GraphicsHandler() {
}
protected:
int32_t width_, height_;
};
#endif // EMBEDDERS_OPENGLUI_COMMON_GRAPHICS_HANDLER_H_

View file

@ -0,0 +1,68 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "embedders/openglui/common/input_handler.h"
#include "embedders/openglui/common/log.h"
InputHandler::InputHandler(VMGlue* vm_glue)
: vm_glue_(vm_glue) {
}
int InputHandler::OnMotionEvent(MotionEvent event,
int64_t when,
float x,
float y) {
const char *function = NULL;
switch (event) {
case kMotionDown:
function = "onMotionDown";
break;
case kMotionUp:
function = "onMotionUp";
break;
case kMotionMove:
function = "onMotionMove";
break;
case kMotionCancel:
function = "onMotionCancel";
break;
case kMotionOutside:
function = "onMotionOutside";
break;
case kMotionPointerDown:
function = "onMotionPointerDown";
break;
case kMotionPointerUp:
function = "onMotionPointerUp";
break;
default:
return -1;
}
return vm_glue_->OnMotionEvent(function, when, x, y);
}
int InputHandler::OnKeyEvent(KeyEvent event,
int64_t when,
int32_t flags,
int32_t key_code,
int32_t meta_state,
int32_t repeat) {
const char *function = NULL;
switch (event) {
case kKeyDown:
function = "onKeyDown";
break;
case kKeyUp:
function = "onKeyUp";
break;
case kKeyMultiple:
function = "onKeyMultiple";
break;
default:
return -1;
}
return vm_glue_->OnKeyEvent(function, when, flags, key_code,
meta_state, repeat);
}

View file

@ -0,0 +1,27 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_COMMON_INPUT_HANDLER_H_
#define EMBEDDERS_OPENGLUI_COMMON_INPUT_HANDLER_H_
#include "embedders/openglui/common/events.h"
#include "embedders/openglui/common/vm_glue.h"
class InputHandler {
public:
explicit InputHandler(VMGlue* vm_glue);
virtual int32_t Start() { return 0; }
virtual void Stop() { }
virtual int OnMotionEvent(MotionEvent event, int64_t when,
float move_x, float move_y);
virtual int OnKeyEvent(KeyEvent event, int64_t when, int32_t flags,
int32_t key_code, int32_t meta_state, int32_t repeat);
virtual ~InputHandler() {}
protected:
VMGlue* vm_glue_;
};
#endif // EMBEDDERS_OPENGLUI_COMMON_INPUT_HANDLER_H_

View file

@ -0,0 +1,19 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_COMMON_ISIZED_H_
#define EMBEDDERS_OPENGLUI_COMMON_ISIZED_H_
// An interface for objects that have a size. VMGlue needs the window
// size when calling setup() (and eventually resize()) but it does not
// need to know anything else about the window, so we use this interface.
class ISized {
public:
virtual const int32_t& height() = 0;
virtual const int32_t& width() = 0;
virtual ~ISized() {}
};
#endif // EMBEDDERS_OPENGLUI_COMMON_ISIZED_H_

View file

@ -0,0 +1,29 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_COMMON_LIFECYCLE_HANDLER_H_
#define EMBEDDERS_OPENGLUI_COMMON_LIFECYCLE_HANDLER_H_
class LifeCycleHandler {
public:
virtual int32_t OnActivate() = 0;
virtual void OnDeactivate() = 0;
virtual int32_t OnStep() = 0;
virtual void OnStart() {}
virtual void OnResume() {}
virtual void OnPause() {}
virtual void OnStop() {}
virtual void OnDestroy() {}
virtual void OnSaveState(void** data, size_t* size) {}
virtual void OnConfigurationChanged() {}
virtual void OnLowMemory() {}
virtual void OnCreateWindow() {}
virtual void OnDestroyWindow() {}
virtual void OnGainedFocus() {}
virtual void OnLostFocus() {}
virtual ~LifeCycleHandler() {}
};
#endif // EMBEDDERS_OPENGLUI_COMMON_LIFECYCLE_HANDLER_H_

View file

@ -0,0 +1,17 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_COMMON_LOG_H_
#define EMBEDDERS_OPENGLUI_COMMON_LOG_H_
#ifndef ANDROID
#include <stdio.h>
#define LOGI(...) fprintf(stdout, __VA_ARGS__)
#define LOGE(...) fprintf(stderr, __VA_ARGS__)
#else
#include "embedders/openglui/android/android_log.h"
#endif
#endif // EMBEDDERS_OPENGLUI_COMMON_LOG_H_

View file

@ -0,0 +1,43 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// A semi-generic header file that can be used to isolate platform differences
// for OpenGL headers.
#ifndef EMBEDDERS_OPENGLUI_COMMON_OPENGL_H_
#define EMBEDDERS_OPENGLUI_COMMON_OPENGL_H_
#if defined(__APPLE__)
# ifdef GL_ES_VERSION_2_0
# include <OpenGLES/ES2/gl.h>
# else
# include <Glut/glut.h>
# include <OpenGL/gl.h>
# endif
# define GLSwapBuffers() glutSwapBuffers()
#elif defined(_WIN32) || defined(_WIN64)
# include <GL/glew.h>
# include <GL/wglew.h>
# include <GLUT/glut.h>
# include <Windows.h>
# define GLSwapBuffers() glutSwapBuffers()
#elif defined(__ANDROID__)
# include <EGL/egl.h>
# include <GLES2/gl2.h>
# include <GLES2/gl2ext.h>
# define GLSwapBuffers() \
do {\
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); \
EGLSurface surface = eglGetCurrentSurface(EGL_DRAW); \
eglSwapBuffers(display, surface); \
} while (0);
#else // Linux.
# define GL_GLEXT_PROTOTYPES 1
# include <GL/gl.h>
# include <GL/glext.h>
# include <GL/glut.h>
# define GLSwapBuffers() glutSwapBuffers()
#endif
#endif // EMBEDDERS_OPENGLUI_COMMON_OPENGL_H_

View file

@ -0,0 +1,57 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_COMMON_RESOURCE_H_
#define EMBEDDERS_OPENGLUI_COMMON_RESOURCE_H_
#include <stdlib.h>
class Resource {
public:
explicit Resource(const char* path)
: path_(path),
descriptor_(-1),
start_(0),
length_(-1) {
}
const char* path() {
return path_;
}
virtual int32_t descriptor() {
return descriptor_;
}
virtual off_t start() {
return start_;
}
virtual off_t length() {
return length_;
}
virtual int32_t Open() {
return -1;
}
virtual void Close() {
}
virtual int32_t Read(void* buffer, size_t count) {
return -1;
}
virtual ~Resource() {
}
protected:
const char* path_;
int32_t descriptor_;
off_t start_;
off_t length_;
};
#endif // EMBEDDERS_OPENGLUI_COMMON_RESOURCE_H_

View file

@ -0,0 +1,60 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_COMMON_SAMPLE_H_
#define EMBEDDERS_OPENGLUI_COMMON_SAMPLE_H_
#include "embedders/openglui/common/resource.h"
class Sample {
public:
explicit Sample(const char* path)
: resource_(path),
buffer_(NULL),
length_(0) {
}
~Sample() {
Unload();
}
const char* path() {
return resource_.path();
}
uint8_t* buffer() {
return buffer_;
}
off_t length() {
return length_;
}
int32_t Load() {
int32_t rtn = -1;
if (resource_.Open() == 0) {
buffer_ = new uint8_t[length_ = resource_.length()];
rtn = resource_.Read(buffer_, length_);
resource_.Close();
}
return rtn;
}
void Unload() {
if (buffer_ != NULL) {
delete[] buffer_;
buffer_ = NULL;
}
length_ = 0;
}
private:
friend class SoundService;
Resource resource_;
uint8_t* buffer_;
off_t length_;
};
#endif // EMBEDDERS_OPENGLUI_COMMON_SAMPLE_H_

View file

@ -0,0 +1,52 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "embedders/openglui/common/sound_handler.h"
#include <string.h>
#include "embedders/openglui/common/log.h"
SoundHandler* SoundHandler::instance_ = NULL;
SoundHandler::SoundHandler()
: samples_() {
}
Sample* SoundHandler::GetSample(const char* path) {
for (samples_t::iterator sp = samples_.begin();
sp != samples_.end();
++sp) {
Sample* sample = (*sp);
if (strcmp(sample->path(), path) == 0) {
return sample;
}
}
Sample* sample = new Sample(path);
if (sample->Load() != 0) {
LOGI("Failed to load sample %s", path);
delete sample;
return NULL;
}
samples_.push_back(sample);
return sample;
}
int32_t PlayBackgroundSound(const char* path) {
return SoundHandler::instance()->PlayBackground(path);
}
void StopBackgroundSound() {
SoundHandler::instance()->StopBackground();
}
int32_t LoadSoundSample(const char* path) {
return SoundHandler::instance()->LoadSample(path);
}
int32_t PlaySoundSample(const char* path) {
return SoundHandler::instance()->PlaySample(path);
}

View file

@ -0,0 +1,63 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_COMMON_SOUND_HANDLER_H_
#define EMBEDDERS_OPENGLUI_COMMON_SOUND_HANDLER_H_
#include <stdint.h>
#include <vector>
#include "embedders/openglui/common/sample.h"
class SoundHandler {
public:
SoundHandler();
virtual ~SoundHandler() {
}
virtual int32_t Start() {
return 0;
}
virtual void Stop() {
}
virtual int32_t PlayBackground(const char* path) {
return 0;
}
virtual void StopBackground() {
}
// Optional, for preloading.
int32_t LoadSample(const char* path) {
return (GetSample(path) == NULL) ? -1 : 0;
}
virtual int32_t PlaySample(const char* path) {
return 0;
}
static SoundHandler* instance() {
return instance_;
}
protected:
typedef std::vector<Sample*> samples_t;
Sample* GetSample(const char* path);
samples_t samples_;
static SoundHandler* instance_;
};
int32_t PlayBackgroundSound(const char* path);
void StopBackgroundSound();
int32_t LoadSoundSample(const char* path);
int32_t PlaySoundSample(const char* path);
#endif // EMBEDDERS_OPENGLUI_COMMON_SOUND_HANDLER_H_

View file

@ -0,0 +1,66 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "embedders/openglui/common/timer.h"
#define NANO (+1.0E-9)
#ifdef __MACH__
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <sys/time.h>
#define GIGA UINT64_C(1000000000)
#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 1
double timebase = 0.0;
uint64_t timestart = 0;
void clock_gettime(int type, timespec* t) {
if (!timestart) {
mach_timebase_info_data_t tb = { 0, 1 };
mach_timebase_info(&tb);
timebase = tb.numer;
timebase /= tb.denom;
timestart = mach_absolute_time();
}
if (type == CLOCK_MONOTONIC) {
double diff = (mach_absolute_time() - timestart) * timebase;
t->tv_sec = diff * NANO;
t->tv_nsec = diff - (t->tv_sec * GIGA);
} else { // type == CLOCK_REALTIME
struct timeval now;
gettimeofday(&now, NULL);
t->tv_sec = now.tv_sec;
t->tv_nsec = now.tv_usec * 1000;
}
}
#endif
Timer::Timer() : elapsed_(0.0f), last_time_(0.0) {
}
void Timer::reset() {
elapsed_ = 0.0f;
last_time_ = now();
}
void Timer::update() {
double current = now();
elapsed_ = (current - last_time_);
last_time_ = current;
}
double Timer::now() {
timespec timeval;
clock_gettime(CLOCK_MONOTONIC, &timeval);
return timeval.tv_sec + (timeval.tv_nsec * NANO);
}
float Timer::elapsed() {
return elapsed_;
}

View file

@ -0,0 +1,24 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_COMMON_TIMER_H_
#define EMBEDDERS_OPENGLUI_COMMON_TIMER_H_
#include <time.h>
class Timer {
public:
Timer();
void reset();
void update();
double now();
float elapsed();
private:
float elapsed_;
double last_time_;
};
#endif // EMBEDDERS_OPENGLUI_COMMON_TIMER_H_

View file

@ -0,0 +1,24 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_COMMON_TYPES_H_
#define EMBEDDERS_OPENGLUI_COMMON_TYPES_H_
struct Location {
Location() : pos_x_(0), pos_y_(0) {
};
void setPosition(float pos_x, float pos_y) {
pos_x_ = pos_x;
pos_y_ = pos_y;
}
void translate(float amount_x, float amount_y) {
pos_x_ += amount_x;
pos_y_ += amount_y;
}
float pos_x_, pos_y_;
};
#endif // EMBEDDERS_OPENGLUI_COMMON_TYPES_H_

View file

@ -0,0 +1,344 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "embedders/openglui/common/extension.h"
#include "embedders/openglui/common/log.h"
#include "embedders/openglui/common/vm_glue.h"
#include "include/dart_api.h"
char* VMGlue::extension_script_ = NULL;
// snapshot_buffer points to a snapshot if we link in a snapshot otherwise
// it is initialized to NULL.
VMGlue::VMGlue(ISized* surface,
const char* script_path,
const char* extension_script,
const char* main_script)
: surface_(surface),
isolate_(NULL),
initialized_vm_(false),
initialized_script_(false) {
LOGI("Creating VMGlue");
if (main_script == NULL) {
main_script = "main.dart";
}
if (extension_script == NULL) {
extension_script = "gl.dart";
}
size_t len = strlen(script_path) + strlen(main_script) + 2;
main_script_ = new char[len];
snprintf(main_script_, len, "%s/%s", script_path, main_script);
len = strlen(script_path) + strlen(extension_script) + 2;
extension_script_ = new char[len];
snprintf(extension_script_, len, "%s/%s", script_path, extension_script);
}
int VMGlue::ErrorExit(const char* format, ...) {
va_list arguments;
va_start(arguments, format);
LOGE(format, arguments);
va_end(arguments);
Dart_ExitScope();
Dart_ShutdownIsolate();
LOGE("Shutdown isolate");
return -1;
}
Dart_Handle VMGlue::CheckError(Dart_Handle handle) {
if (Dart_IsError(handle)) {
LOGE("Unexpected Error Handle: %s", Dart_GetError(handle));
Dart_PropagateError(handle);
}
return handle;
}
#define CHECK_RESULT(result) \
if (Dart_IsError(result)) { \
*error = strdup(Dart_GetError(result)); \
LOGE("%s", *error); \
Dart_ExitScope(); \
Dart_ShutdownIsolate(); \
return false; \
}
Dart_Handle VMGlue::LibraryTagHandler(Dart_LibraryTag tag,
Dart_Handle library,
Dart_Handle urlHandle) {
const char* url;
Dart_StringToCString(urlHandle, &url);
if (tag == kCanonicalizeUrl) {
return urlHandle;
}
// TODO(vsm): Split this up into separate libraries for 3D, 2D,
// Touch, Audio, etc. All builtin libraries should be handled here
// (or moved into a snapshot).
if (strcmp(url, "gl.dart") == 0) {
Dart_Handle source =
VMGlue::LoadSourceFromFile(extension_script_);
Dart_Handle library = CheckError(Dart_LoadLibrary(urlHandle, source));
CheckError(Dart_SetNativeResolver(library, ResolveName));
return library;
}
LOGE("UNIMPLEMENTED: load library %s\n", url);
return NULL;
}
// Returns true on success, false on failure.
bool VMGlue::CreateIsolateAndSetupHelper(const char* script_uri,
const char* main,
void* data,
char** error) {
LOGI("Creating isolate %s, %s", script_uri, main);
Dart_Isolate isolate =
Dart_CreateIsolate(script_uri, main, NULL, data, error);
if (isolate == NULL) {
LOGE("Couldn't create isolate: %s", *error);
return false;
}
LOGI("Entering scope");
Dart_EnterScope();
// Set up the library tag handler for this isolate.
LOGI("Setting up library tag handler");
Dart_Handle result = CheckError(Dart_SetLibraryTagHandler(LibraryTagHandler));
CHECK_RESULT(result);
Dart_ExitScope();
return true;
}
bool VMGlue::CreateIsolateAndSetup(const char* script_uri,
const char* main,
void* data, char** error) {
return CreateIsolateAndSetupHelper(script_uri,
main,
data,
error);
}
const char* VM_FLAGS[] = {
"--enable_type_checks", // TODO(gram): This should be an option!
"--trace_isolates",
"--trace_natives",
};
int VMGlue::InitializeVM() {
// We need the next call to get Dart_Initialize not to bail early.
LOGI("Setting VM Options");
Dart_SetVMFlags(sizeof(VM_FLAGS) / sizeof(VM_FLAGS[0]), VM_FLAGS);
// Initialize the Dart VM, providing the callbacks to use for
// creating and shutting down isolates.
LOGI("Initializing Dart");
if (!Dart_Initialize(CreateIsolateAndSetup,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL)) {
LOGE("VM initialization failed\n");
return -1;
}
initialized_vm_ = true;
return 0;
}
Dart_Handle VMGlue::LoadSourceFromFile(const char* url) {
FILE* file = fopen(url, "r");
if (file == NULL) {
LOGE("Main script not found at: %s\n", url);
return NULL;
}
struct stat sb;
int fd = fileno(file);
fstat(fd, &sb);
int length = sb.st_size;
LOGI("Entry file %s is %d bytes.\n", url, length);
char* buffer = new char[length+1];
if (read(fd, buffer, length) < 0) {
LOGE("Could not read script %s.\n", url);
return NULL;
}
buffer[length] = 0;
fclose(file);
Dart_Handle contents = CheckError(Dart_NewStringFromCString(buffer));
delete[] buffer;
return contents;
}
int VMGlue::StartMainIsolate() {
if (!initialized_vm_) {
int rtn = InitializeVM();
if (rtn != 0) return rtn;
}
// Create an isolate and loads up the application script.
char* error = NULL;
if (!CreateIsolateAndSetup(main_script_, "main", NULL, &error)) {
LOGE("CreateIsolateAndSetup: %s\n", error);
free(error);
return -1;
}
LOGI("Created isolate");
isolate_ = Dart_CurrentIsolate();
Dart_EnterScope();
Dart_Handle url = CheckError(Dart_NewStringFromCString(main_script_));
Dart_Handle source = LoadSourceFromFile(main_script_);
CheckError(Dart_LoadScript(url, source));
Dart_ExitScope();
Dart_ExitIsolate();
return 0;
}
int VMGlue::CallSetup() {
if (!initialized_script_) {
initialized_script_ = true;
LOGI("Invoking setup(0,0,%d,%d)", surface_->width(), surface_->height());
Dart_EnterIsolate(isolate_);
Dart_EnterScope();
Dart_Handle args[2];
args[0] = CheckError(Dart_NewInteger(surface_->width()));
args[1] = CheckError(Dart_NewInteger(surface_->height()));
int rtn = Invoke("setup", 2, args);
if (rtn == 0) {
// Plug in the print handler. It would be nice if we could do this
// before calling setup, but the call to GetField blows up if we
// haven't run anything yet.
Dart_Handle library = CheckError(Dart_LookupLibrary(
Dart_NewStringFromCString("gl.dart")));
Dart_Handle print = CheckError(
Dart_GetField(library, Dart_NewStringFromCString("_printClosure")));
Dart_Handle corelib = CheckError(Dart_LookupLibrary(
Dart_NewStringFromCString("dart:core")));
CheckError(Dart_SetField(corelib,
Dart_NewStringFromCString("_printClosure"), print));
}
Dart_ExitScope();
Dart_ExitIsolate();
LOGI("Done setup");
return rtn;
}
return 0;
}
int VMGlue::CallUpdate() {
if (initialized_script_) {
LOGI("Invoking update");
Dart_EnterIsolate(isolate_);
Dart_EnterScope();
int rtn = Invoke("update", 0, 0);
Dart_ExitScope();
Dart_ExitIsolate();
LOGI("Done update");
return rtn;
}
return -1;
}
int VMGlue::OnMotionEvent(const char* pFunction, int64_t pWhen,
float pMoveX, float pMoveY) {
if (initialized_script_) {
LOGI("Invoking %s", pFunction);
Dart_EnterIsolate(isolate_);
Dart_EnterScope();
Dart_Handle args[3];
args[0] = CheckError(Dart_NewInteger(pWhen));
args[1] = CheckError(Dart_NewDouble(pMoveX));
args[2] = CheckError(Dart_NewDouble(pMoveY));
int rtn = Invoke(pFunction, 3, args, false);
Dart_ExitScope();
Dart_ExitIsolate();
LOGI("Done %s", pFunction);
return rtn;
}
return -1;
}
int VMGlue::OnKeyEvent(const char* function, int64_t when, int32_t flags,
int32_t key_code, int32_t meta_state, int32_t repeat) {
if (initialized_script_) {
LOGI("Invoking %s", function);
Dart_EnterIsolate(isolate_);
Dart_EnterScope();
Dart_Handle args[5];
args[0] = CheckError(Dart_NewInteger(when));
args[1] = CheckError(Dart_NewInteger(flags));
args[2] = CheckError(Dart_NewInteger(key_code));
args[3] = CheckError(Dart_NewInteger(meta_state));
args[4] = CheckError(Dart_NewInteger(repeat));
int rtn = Invoke(function, 5, args, false);
Dart_ExitScope();
Dart_ExitIsolate();
LOGI("Done %s", function);
return rtn;
}
return -1;
}
int VMGlue::Invoke(const char* function,
int argc,
Dart_Handle* args,
bool failIfNotDefined) {
LOGI("in invoke(%s)", function);
// Lookup the library of the root script.
LOGI("looking up the root library");
Dart_Handle library = Dart_RootLibrary();
if (Dart_IsNull(library)) {
return ErrorExit("Unable to find root library\n");
}
Dart_Handle nameHandle = Dart_NewStringFromCString(function);
LOGI("invoking %s", function);
Dart_Handle result = Dart_Invoke(library, nameHandle, argc, args);
if (Dart_IsError(result)) {
if (failIfNotDefined) {
return ErrorExit("Invoke %s: %s\n", function, Dart_GetError(result));
} else {
LOGE("Invoke %s: %s", function, Dart_GetError(result));
}
}
// TODO(vsm): I don't think we need this.
// Keep handling messages until the last active receive port is closed.
LOGI("Entering Dart message loop");
result = Dart_RunLoop();
if (Dart_IsError(result)) {
return ErrorExit("Dart_RunLoop: %s\n", Dart_GetError(result));
}
LOGI("out invoke");
return 0;
}
void VMGlue::FinishMainIsolate() {
LOGI("Finish main isolate");
Dart_EnterIsolate(isolate_);
// Shutdown the isolate.
Dart_ShutdownIsolate();
isolate_ = NULL;
initialized_script_ = false;
}

View file

@ -0,0 +1,64 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_COMMON_VM_GLUE_H_
#define EMBEDDERS_OPENGLUI_COMMON_VM_GLUE_H_
#include <stdlib.h>
#include "embedders/openglui/common/events.h"
#include "embedders/openglui/common/isized.h"
#include "include/dart_api.h"
class VMGlue {
public:
explicit VMGlue(ISized* surface,
const char* script_path,
const char* extension_script = NULL,
const char* main_script = NULL);
~VMGlue() {
delete[] main_script_;
delete[] extension_script_;
}
int InitializeVM();
int StartMainIsolate();
int CallSetup();
int CallUpdate();
int OnMotionEvent(const char* funtion, int64_t when,
float move_x, float move_y);
int OnKeyEvent(const char* funtion, int64_t when, int32_t flags,
int32_t key_code, int32_t meta_state, int32_t repeat);
void FinishMainIsolate();
private:
int Invoke(const char *function, int argc, Dart_Handle* args,
bool failIfNotDefined = true);
static int ErrorExit(const char* format, ...);
static Dart_Handle CheckError(Dart_Handle);
static bool CreateIsolateAndSetupHelper(const char* script_uri,
const char* main,
void* data,
char** error);
static bool CreateIsolateAndSetup(const char* script_uri,
const char* main,
void* data, char** error);
static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag,
Dart_Handle library,
Dart_Handle urlHandle);
static Dart_Handle LoadSourceFromFile(const char* url);
static void ShutdownIsolate(void* callback_data);
ISized* surface_;
Dart_Isolate isolate_;
bool initialized_vm_;
bool initialized_script_;
char* main_script_;
static char* extension_script_;
};
#endif // EMBEDDERS_OPENGLUI_COMMON_VM_GLUE_H_

View file

@ -0,0 +1,73 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "embedders/openglui/emulator/emulator_embedder.h"
#include <string.h>
#include "embedders/openglui/common/context.h"
#include "embedders/openglui/common/dart_host.h"
#include "embedders/openglui/common/events.h"
#include "embedders/openglui/common/input_handler.h"
#include "embedders/openglui/common/sound_handler.h"
#include "embedders/openglui/common/vm_glue.h"
#include "embedders/openglui/emulator/emulator_graphics_handler.h"
InputHandler* input_handler_ptr;
LifeCycleHandler* lifecycle_handler_ptr;
void display() {
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
lifecycle_handler_ptr->OnStep();
glutSwapBuffers();
}
void reshape(int width, int height) {
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, 0, height, -1, 1);
glMatrixMode(GL_MODELVIEW);
glutPostRedisplay();
}
void keyboard(unsigned char key, int x, int y) {
input_handler_ptr->OnKeyEvent(kKeyDown, time(0), 0, key, 0, 0);
input_handler_ptr->OnKeyEvent(kKeyUp, time(0), 0, key, 0, 0);
if (key == 27) {
exit(0);
}
}
DART_EXPORT void emulator_main(int argc, char** argv, const char* script) {
EmulatorGraphicsHandler graphics_handler(argc, argv);
if (argc > 0) {
int i = argc - 1;
size_t len = strlen(argv[i]);
if (len > 5 && strcmp(".dart", argv[i] + len - 5) == 0) {
script = argv[i];
}
}
VMGlue vm_glue(&graphics_handler, ".", "gl.dart", script);
InputHandler input_handler(&vm_glue);
input_handler_ptr = &input_handler;
SoundHandler sound_handler;
Timer timer;
Context app_context;
app_context.graphics_handler = &graphics_handler;
app_context.input_handler = &input_handler;
app_context.sound_handler = &sound_handler;
app_context.timer = &timer;
app_context.vm_glue = &vm_glue;
DartHost host(&app_context);
lifecycle_handler_ptr = &host;
lifecycle_handler_ptr->OnActivate();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutIdleFunc(display);
glutMainLoop();
}

View file

@ -0,0 +1,14 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_EMBEDDER_H_
#define EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_EMBEDDER_H_
#include "include/dart_api.h"
DART_EXPORT void emulator_main(int argc, char** argv,
const char* script);
#endif // EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_EMBEDDER_H_

View file

@ -0,0 +1,38 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "embedders/openglui/emulator/emulator_graphics_handler.h"
#include <stdlib.h>
#include <string.h>
EmulatorGraphicsHandler::EmulatorGraphicsHandler(int argc,
char** argv)
: GLGraphicsHandler() {
glutInit(&argc, argv);
width_ = 480;
height_ = 800;
for (int i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
int next_arg = i + 1;
if (next_arg < argc && strcmp(argv[i], "-w") == 0) {
width_ = static_cast<size_t>(atoi(argv[i = next_arg]));
} else if (next_arg < argc && strcmp(argv[i], "-h") == 0) {
height_ = static_cast<size_t>(atoi(argv[i = next_arg]));
}
}
}
}
int32_t EmulatorGraphicsHandler::Start() {
glutInitWindowSize(width_, height_);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutCreateWindow("Dart");
return 0;
}
void EmulatorGraphicsHandler::Stop() {
exit(0);
}

View file

@ -0,0 +1,19 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_GRAPHICS_HANDLER_H_
#define EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_GRAPHICS_HANDLER_H_
#include "embedders/openglui/common/gl_graphics_handler.h"
class EmulatorGraphicsHandler : public GLGraphicsHandler {
public:
EmulatorGraphicsHandler(int argc, char** argv);
int32_t Start();
void Stop();
};
#endif // EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_GRAPHICS_HANDLER_H_

View file

@ -0,0 +1,63 @@
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_RESOURCE_H_
#define EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_RESOURCE_H_
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "embedders/openglui/common/log.h"
#include "embedders/openglui/common/resource.h"
class EmulatorResource : public Resource {
public:
explicit EmulatorResource(const char* path)
: base(path),
fd_(-1) {
}
int32_t descriptor() {
if (fd_ < 0) {
Open();
}
return fd_;
}
off_t length() {
if (length_ < 0) {
length_ = lseek(fd), 0, SEEK_END);
lseek(fd), 0, SEEK_START);
}
return length_;
}
int32_t Open() {
fd_ = open(path_, 0);
if (fd_ >= 0) {
return 0;
}
LOGE("Could not open asset %s", path_);
return -1;
}
void Close() {
if (fd_ >= 0) {
close(fd_);
fd_ = -1;
}
}
int32_t Read(void* buffer, size_t count) {
size_t actual = read(asset_, buffer, count);
return (actual == count) ? 0 : -1;
}
private:
int fd_;
};
#endif // EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_RESOURCE_H_

View file

@ -0,0 +1,156 @@
# Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
{
'conditions': [
['OS=="android"',
{
'targets': [
{
# Dart shared library for Android.
'target_name': 'android_embedder',
'type': 'shared_library',
'dependencies': [
'libdart_lib_withcore',
'libdart_vm',
'libjscre',
'libdouble_conversion',
'generate_version_cc_file',
],
'include_dirs': [
'../..',
'../../../third_party/android_tools/ndk/sources/android/native_app_glue',
],
'defines': [
'DART_SHARED_LIB',
'__ANDROID__'
],
'sources': [
'../../include/dart_api.h',
'../../include/dart_debugger_api.h',
'../../vm/dart_api_impl.cc',
'../../vm/debugger_api_impl.cc',
'../../vm/version.h',
'../../../third_party/android_tools/ndk/sources/android/native_app_glue/android_native_app_glue.h',
'../../../third_party/android_tools/ndk/sources/android/native_app_glue/android_native_app_glue.c',
'android/android_graphics_handler.cc',
'android/android_graphics_handler.h',
'android/android_input_handler.h',
'android/android_resource.h',
'android/android_sound_handler.cc',
'android/android_sound_handler.h',
'android/eventloop.cc',
'android/eventloop.h',
'android/log.h',
'android/main.cc',
'android/support_android.cc',
'common/context.h',
'common/dart_host.cc',
'common/dart_host.h',
'common/events.h',
'common/extension.cc',
'common/extension.h',
'common/gl_graphics_handler.cc',
'common/gl_graphics_handler.h',
'common/graphics_handler.h',
'common/input_handler.cc',
'common/input_handler.h',
'common/isized.h',
'common/life_cycle_handler.h',
'common/log.h',
'common/opengl.h',
'common/resource.h',
'common/sample.h',
'common/sound_handler.cc',
'common/sound_handler.h',
'common/timer.cc',
'common/timer.h',
'common/types.h',
'common/vm_glue.cc',
'common/vm_glue.h',
'<(version_cc_file)',
],
'link_settings': {
'libraries': [ '-llog', '-lc', '-landroid', '-lEGL', '-lGLESv2', '-lOpenSLES', '-landroid' ],
'ldflags': [
'-z', 'muldefs'
],
'ldflags!': [
'-Wl,--exclude-libs=ALL',
],
},
},
],
},
],
['OS=="mac" or OS=="linux"',
{
'targets': [
{
'target_name': 'emulator_embedder',
'type': 'shared_library',
'dependencies': [
'libdart_lib_withcore',
'libdart_vm',
'libjscre',
'libdouble_conversion',
'generate_version_cc_file',
],
'include_dirs': [
'../..',
],
'defines': [
'DART_SHARED_LIB'
],
'sources': [
'../../include/dart_api.h',
'../../include/dart_debugger_api.h',
'../../vm/dart_api_impl.cc',
'../../vm/debugger_api_impl.cc',
'../../vm/version.h',
'common/context.h',
'common/dart_host.cc',
'common/dart_host.h',
'common/events.h',
'common/extension.cc',
'common/extension.h',
'common/gl_graphics_handler.cc',
'common/gl_graphics_handler.h',
'common/graphics_handler.h',
'common/input_handler.cc',
'common/input_handler.h',
'common/isized.h',
'common/life_cycle_handler.h',
'common/log.h',
'common/opengl.h',
'common/resource.h',
'common/sample.h',
'common/sound_handler.cc',
'common/sound_handler.h',
'common/timer.cc',
'common/timer.h',
'common/types.h',
'common/vm_glue.cc',
'common/vm_glue.h',
'emulator/emulator_embedder.cc',
'emulator/emulator_embedder.h',
'emulator/emulator_graphics_handler.cc',
'emulator/emulator_graphics_handler.h',
'emulator/emulator_resource.h',
'<(version_cc_file)',
],
'conditions': [
['OS=="mac"', {
'xcode_settings' : {
'OTHER_LDFLAGS': [ '-framework OpenGL', '-framework GLUT', '-L /usr/X11/lib' ]
},
}],
]
},
],
},
],
],
}