diff options
Diffstat (limited to 'o3d/plugin/cross')
-rw-r--r-- | o3d/plugin/cross/o3d_glue.cc | 104 | ||||
-rw-r--r-- | o3d/plugin/cross/o3d_glue.h | 37 |
2 files changed, 140 insertions, 1 deletions
diff --git a/o3d/plugin/cross/o3d_glue.cc b/o3d/plugin/cross/o3d_glue.cc index 6a2d53f..0d66e9c 100644 --- a/o3d/plugin/cross/o3d_glue.cc +++ b/o3d/plugin/cross/o3d_glue.cc @@ -37,7 +37,9 @@ #include <string> #include <algorithm> +#include "core/cross/image_utils.h" #include "core/cross/renderer.h" +#include "core/cross/texture.h" #include "core/cross/client_info.h" #include "plugin/cross/o3d_glue.h" #include "plugin/cross/config.h" @@ -56,6 +58,10 @@ namespace glue { namespace _o3d { +using o3d::Bitmap; +using o3d::Texture; +using o3d::Texture2D; + void RegisterType(NPP npp, const ObjectBase::Class *clientclass, NPClass *npclass) { PluginObject *plugin_object = static_cast<PluginObject *>(npp->pdata); @@ -134,6 +140,7 @@ PluginObject::PluginObject(NPP npp) mac_2d_context_(0), mac_agl_context_(0), mac_cgl_context_(0), + mac_cgl_pbuffer_(0), last_mac_event_time_(0), #ifdef O3D_PLUGIN_ENABLE_FULLSCREEN_MSG time_to_hide_overlay_(0.0), @@ -165,7 +172,8 @@ PluginObject::PluginObject(NPP npp) stream_manager_(new StreamManager(npp)), cursor_type_(o3d::Cursor::DEFAULT), prev_width_(0), - prev_height_(0) { + prev_height_(0), + offscreen_rendering_enabled_(false) { #if defined(OS_WIN) || defined(OS_LINUX) memset(cursors_, 0, sizeof(cursors_)); #endif @@ -218,6 +226,7 @@ void PluginObject::Init(int argc, char* argn[], char* argv[]) { } void PluginObject::TearDown() { + DisableOffscreenRendering(); #ifdef OS_WIN ClearPluginProperty(hWnd_); #elif defined(OS_MACOSX) @@ -717,6 +726,12 @@ void PluginObject::Resize(int width, int height) { prev_height_ = height; if (renderer_ && !fullscreen_) { + // If we are rendering offscreen, we may need to reallocate the + // render surfaces. + if (offscreen_rendering_enabled_) { + AllocateOffscreenRenderSurfaces(width, height); + } + // Tell the renderer and client that our window has been resized. // If we're in fullscreen mode when this happens, we don't want to pass // the information through; the renderer will pick it up when we switch @@ -1053,6 +1068,93 @@ void PluginObject::Tick() { } } +void PluginObject::EnableOffscreenRendering() { + if (!offscreen_rendering_enabled_) { + AllocateOffscreenRenderSurfaces(width(), height()); + offscreen_rendering_enabled_ = true; + } +} + +void PluginObject::DisableOffscreenRendering() { + if (offscreen_rendering_enabled_) { + DeallocateOffscreenRenderSurfaces(); + offscreen_rendering_enabled_ = false; + } +} + +bool PluginObject::IsOffscreenRenderingEnabled() const { + return offscreen_rendering_enabled_; +} + +RenderSurface::Ref PluginObject::GetOffscreenRenderSurface() const { + return offscreen_render_surface_; +} + +Bitmap::Ref PluginObject::GetOffscreenBitmap() const { + return offscreen_readback_bitmap_; +} + +bool PluginObject::AllocateOffscreenRenderSurfaces(int width, int height) { + int pot_width = + static_cast<int>(o3d::image::ComputePOTSize(width)); + int pot_height = + static_cast<int>(o3d::image::ComputePOTSize(height)); + if (!renderer_ || pot_width == 0 || pot_height == 0) { + return false; + } + bool must_reallocate_render_surfaces = + (offscreen_render_surface_.IsNull() || + offscreen_depth_render_surface_.IsNull() || + offscreen_render_surface_->width() != pot_width || + offscreen_render_surface_->height() != pot_height); + if (must_reallocate_render_surfaces) { + Texture2D::Ref texture = renderer_->CreateTexture2D( + pot_width, + pot_height, + Texture::ARGB8, + 1, + true); + if (texture.IsNull()) { + return false; + } + RenderSurface::Ref surface(texture->GetRenderSurface(0)); + if (surface.IsNull()) { + return false; + } + RenderDepthStencilSurface::Ref depth(renderer_->CreateDepthStencilSurface( + pot_width, + pot_height)); + if (depth.IsNull()) { + return false; + } + offscreen_texture_ = texture; + offscreen_render_surface_ = surface; + offscreen_depth_render_surface_ = depth; + } + offscreen_render_surface_->SetClipSize(width, height); + offscreen_depth_render_surface_->SetClipSize(width, height); + if (offscreen_readback_bitmap_.IsNull() || + offscreen_readback_bitmap_->width() != width || + offscreen_readback_bitmap_->height() != height) { + o3d::Bitmap::Ref bitmap = Bitmap::Ref( + new Bitmap(service_locator())); + bitmap->Allocate(Texture::ARGB8, + width, height, 1, Bitmap::IMAGE); + offscreen_readback_bitmap_ = bitmap; + } + // Tell the Client about the newly allocated surfaces so that normal + // calls to RenderClient can automatically do the right thing. + client_->SetOffscreenRenderingSurfaces(offscreen_render_surface_, + offscreen_depth_render_surface_); + return true; +} + +void PluginObject::DeallocateOffscreenRenderSurfaces() { + offscreen_render_surface_.Reset(); + offscreen_depth_render_surface_.Reset(); + offscreen_readback_bitmap_.Reset(); +} + } // namespace _o3d namespace globals { diff --git a/o3d/plugin/cross/o3d_glue.h b/o3d/plugin/cross/o3d_glue.h index 8911804..c335665 100644 --- a/o3d/plugin/cross/o3d_glue.h +++ b/o3d/plugin/cross/o3d_glue.h @@ -53,6 +53,7 @@ #include <vector> #include "base/scoped_ptr.h" #include "base/hash_tables.h" +#include "core/cross/bitmap.h" #include "core/cross/display_mode.h" #include "core/cross/display_window.h" #include "core/cross/object_base.h" @@ -65,6 +66,8 @@ #include "core/cross/object_manager.h" #include "core/cross/error.h" #include "core/cross/profiler.h" +#include "core/cross/render_surface.h" +#include "core/cross/texture.h" #include "plugin/cross/main_thread_task_poster.h" #include "plugin/cross/np_v8_bridge.h" #include "client_glue.h" @@ -116,6 +119,7 @@ class StreamManager; namespace _o3d { using o3d::Id; using o3d::ObjectBase; +using o3d::Bitmap; using o3d::Client; using o3d::ClassManager; using o3d::ClientInfoManager; @@ -126,7 +130,10 @@ using o3d::MainThreadTaskPoster; using o3d::ObjectManager; using o3d::Profiler; using o3d::Renderer; +using o3d::RenderSurface; +using o3d::RenderDepthStencilSurface; using o3d::ServiceLocator; +using o3d::Texture2D; class NPAPIObject: public NPObject { NPP npp_; @@ -268,6 +275,9 @@ class PluginObject: public NPObject { // either can be NULL depending on drawing_model AGLContext mac_agl_context_; CGLContextObj mac_cgl_context_; + // If in Chrome, we actually do all of our rendering offscreen, and + // bootstrap off a 1x1 pbuffer + CGLPBufferObj mac_cgl_pbuffer_; // Fullscreen related stuff. @@ -475,6 +485,19 @@ class PluginObject: public NPObject { } #endif + // Support for rendering the plugin's content into render surfaces. + // This is currently different than offscreen rendering support in + // the renderer. It is a bit of a mess because only the PluginObject + // and Renderer have the necessary information about the viewport + // size, and only the Client has enough information to properly + // initiate a render. + void EnableOffscreenRendering(); + void DisableOffscreenRendering(); + bool IsOffscreenRenderingEnabled() const; + RenderSurface::Ref GetOffscreenRenderSurface() const; + RenderDepthStencilSurface::Ref GetOffscreenDepthRenderSurface() const; + Bitmap::Ref GetOffscreenBitmap() const; + private: bool fullscreen_region_valid_; int fullscreen_region_x_; @@ -497,6 +520,20 @@ class PluginObject: public NPObject { #if defined(CB_SERVICE_REMOTE) NPObject* gpu_plugin_object_; #endif + + // Support for offscreen rendering and thereby windowless plugins. + // Currently used only for the CoreGraphics drawing model on Mac OS + // X when there is no WindowRef. It would be nicer to put this in + // the Renderer and/or make its off_screen mode work everywhere, but + // this is only a legacy solution for older browsers. + bool offscreen_rendering_enabled_; + Texture2D::Ref offscreen_texture_; + RenderSurface::Ref offscreen_render_surface_; + RenderDepthStencilSurface::Ref offscreen_depth_render_surface_; + Bitmap::Ref offscreen_readback_bitmap_; + + bool AllocateOffscreenRenderSurfaces(int width, int height); + void DeallocateOffscreenRenderSurfaces(); }; } // namespace o3d |