summaryrefslogtreecommitdiffstats
path: root/o3d
diff options
context:
space:
mode:
Diffstat (limited to 'o3d')
-rw-r--r--o3d/core/cross/client.cc4
-rw-r--r--o3d/core/cross/client.h5
-rw-r--r--o3d/plugin/mac/main_mac.mm65
-rw-r--r--o3d/plugin/mac/plugin_mac.mm6
4 files changed, 48 insertions, 32 deletions
diff --git a/o3d/core/cross/client.cc b/o3d/core/cross/client.cc
index f66816c..0097d67 100644
--- a/o3d/core/cross/client.cc
+++ b/o3d/core/cross/client.cc
@@ -339,6 +339,10 @@ void Client::RenderClient(bool send_callback) {
}
}
+bool Client::IsRendering() {
+ return (renderer_.IsAvailable() && renderer_->rendering());
+}
+
// Executes draw calls for all visible shapes in a subtree
void Client::RenderTree(RenderNode *tree_root) {
if (!renderer_.IsAvailable())
diff --git a/o3d/core/cross/client.h b/o3d/core/cross/client.h
index 18c15a8..158f1eb 100644
--- a/o3d/core/cross/client.h
+++ b/o3d/core/cross/client.h
@@ -259,6 +259,11 @@ class Client {
// go.
void RenderClient(bool send_callback);
+ // In some situations (on Mac OS X at least) calling the user's
+ // render callback can cause OS events to be dispatched which cause
+ // the plugin to become reentrant. Detect this at a higher level.
+ bool IsRendering();
+
// Sets the texture to use when a Texture or Sampler is missing while
// rendering. If you set it to NULL you'll get an error if you try to render
// something that is missing a needed Texture, Sampler or ParamSampler
diff --git a/o3d/plugin/mac/main_mac.mm b/o3d/plugin/mac/main_mac.mm
index 328c84b..3e05180 100644
--- a/o3d/plugin/mac/main_mac.mm
+++ b/o3d/plugin/mac/main_mac.mm
@@ -1043,39 +1043,40 @@ NPError NPP_SetWindow(NPP instance, NPWindow* window) {
if (obj->mac_cgl_context_) {
CGLSetCurrentContext(obj->mac_cgl_context_);
}
- } else if (obj->drawing_model_ == NPDrawingModelCoreGraphics &&
- obj->mac_cgl_pbuffer_ == NULL) {
- // We initialize things with a CGL context rendering to a 1x1
- // pbuffer. Later we use the O3D RenderSurface APIs to set up the
- // framebuffer object which is used for rendering.
- CGLContextObj share_context = obj->GetFullscreenShareContext();
- CGLPixelFormatObj pixel_format = obj->GetFullscreenCGLPixelFormatObj();
- DCHECK(share_context);
- CGLError result;
- CGLContextObj context;
- result = CGLCreateContext(pixel_format, share_context, &context);
- if (result != kCGLNoError) {
- DLOG(ERROR) << "Error " << result << " creating context.";
- return NPERR_GENERIC_ERROR;
- }
- CGLPBufferObj pbuffer;
- if ((result = CGLCreatePBuffer(1, 1,
- GL_TEXTURE_2D, GL_RGBA,
- 0, &pbuffer)) != kCGLNoError) {
- CGLDestroyContext(context);
- DLOG(ERROR) << "Error " << result << " creating pbuffer.";
- return NPERR_GENERIC_ERROR;
- }
- if ((result = CGLSetPBuffer(context, pbuffer, 0, 0, 0)) != kCGLNoError) {
- CGLDestroyContext(context);
- CGLDestroyPBuffer(pbuffer);
- DLOG(ERROR) << "Error " << result << " attaching pbuffer to context.";
- return NPERR_GENERIC_ERROR;
+ } else if (obj->drawing_model_ == NPDrawingModelCoreGraphics) {
+ if (obj->mac_cgl_pbuffer_ == NULL) {
+ // We initialize things with a CGL context rendering to a 1x1
+ // pbuffer. Later we use the O3D RenderSurface APIs to set up the
+ // framebuffer object which is used for rendering.
+ CGLContextObj share_context = obj->GetFullscreenShareContext();
+ CGLPixelFormatObj pixel_format = obj->GetFullscreenCGLPixelFormatObj();
+ DCHECK(share_context);
+ CGLError result;
+ CGLContextObj context;
+ result = CGLCreateContext(pixel_format, share_context, &context);
+ if (result != kCGLNoError) {
+ DLOG(ERROR) << "Error " << result << " creating context.";
+ return NPERR_GENERIC_ERROR;
+ }
+ CGLPBufferObj pbuffer;
+ if ((result = CGLCreatePBuffer(1, 1,
+ GL_TEXTURE_2D, GL_RGBA,
+ 0, &pbuffer)) != kCGLNoError) {
+ CGLDestroyContext(context);
+ DLOG(ERROR) << "Error " << result << " creating pbuffer.";
+ return NPERR_GENERIC_ERROR;
+ }
+ if ((result = CGLSetPBuffer(context, pbuffer, 0, 0, 0)) != kCGLNoError) {
+ CGLDestroyContext(context);
+ CGLDestroyPBuffer(pbuffer);
+ DLOG(ERROR) << "Error " << result << " attaching pbuffer to context.";
+ return NPERR_GENERIC_ERROR;
+ }
+ // Must make the context current for renderer creation to succeed
+ CGLSetCurrentContext(context);
+ obj->mac_cgl_context_ = context;
+ obj->mac_cgl_pbuffer_ = pbuffer;
}
- // Must make the context current for renderer creation to succeed
- CGLSetCurrentContext(context);
- obj->mac_cgl_context_ = context;
- obj->mac_cgl_pbuffer_ = pbuffer;
} else if (!had_a_window && obj->mac_agl_context_ == NULL) {
// setup AGL context
AGLPixelFormat myAGLPixelFormat = NULL;
diff --git a/o3d/plugin/mac/plugin_mac.mm b/o3d/plugin/mac/plugin_mac.mm
index 071890b..488a7b6 100644
--- a/o3d/plugin/mac/plugin_mac.mm
+++ b/o3d/plugin/mac/plugin_mac.mm
@@ -237,6 +237,12 @@ void RenderTimer::TimerCallback(CFRunLoopTimerRef timer, void* info) {
NPP instance = instances_[i];
PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
+ // RenderClient() may cause events to be processed, leading to
+ // reentrant calling of this code. Detect and avoid this case.
+ if (obj->client()->IsRendering()) {
+ continue;
+ }
+
bool in_fullscreen = obj->GetFullscreenMacWindow();
if (obj->drawing_model_ == NPDrawingModelCoreAnimation &&