diff options
Diffstat (limited to 'o3d')
-rw-r--r-- | o3d/core/cross/client.cc | 4 | ||||
-rw-r--r-- | o3d/core/cross/client.h | 5 | ||||
-rw-r--r-- | o3d/plugin/mac/main_mac.mm | 65 | ||||
-rw-r--r-- | o3d/plugin/mac/plugin_mac.mm | 6 |
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 && |