diff options
author | kbr@chromium.org <kbr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-11 01:26:00 +0000 |
---|---|---|
committer | kbr@chromium.org <kbr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-11 01:26:00 +0000 |
commit | 8a304130d6d53bae89ae6023e64b261624ed5ddf (patch) | |
tree | 1b58beab34926aa5eab2f5b2ce866d9a31a6925a /o3d/plugin/cross | |
parent | b93cc8295f42e55bb2bec5e444918a8cd20da069 (diff) | |
download | chromium_src-8a304130d6d53bae89ae6023e64b261624ed5ddf.zip chromium_src-8a304130d6d53bae89ae6023e64b261624ed5ddf.tar.gz chromium_src-8a304130d6d53bae89ae6023e64b261624ed5ddf.tar.bz2 |
Added support for O3D in Chrome on Mac OS X using CoreGraphics drawing
model by rendering offscreen, reading back the frame buffer, and
drawing the rendering results into the CGContextRef.
This code path is currently Chrome-specific, but could be used for any
browser with similar characteristics. This will require refactoring of
the drawing and event model selection code, which may be done in a
subsequent bug.
Changed the RenderSurface APIs to allow the Bitmap for readback to be
passed in. Added Client::SetOffscreenRenderingSurfaces so that the
entry point Client::RenderClient() can be used unchanged.
Fixed problem with plugin_enable_fullscreen_msg gyp variable which
needs to be in top-level gypi so #define is consistent throughout
project. Fixed minor issue in Cocoa key event handling. Fixed log
message causing crashes when render target attachment fails.
Chrome currently blacklists the O3D plugin's MIME type, so to enable
support for O3D this blacklist entry needs to be removed from Chrome.
Ran nearly all O3D samples in Chrome on Mac OS X. There are a couple
of failures which will be fixed in subsequent bugs. Also ran samples
in Safari and Firefox on Mac and verified no performance regressions.
BUG=http://code.google.com/p/o3d/issues/detail?id=215
TEST=ran O3D samples in Chrome, Safari and Firefox
Review URL: http://codereview.chromium.org/669220
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41233 0039d316-1c4b-4281-b951-d872f2087c98
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 |