summaryrefslogtreecommitdiffstats
path: root/o3d/plugin/cross
diff options
context:
space:
mode:
Diffstat (limited to 'o3d/plugin/cross')
-rw-r--r--o3d/plugin/cross/o3d_glue.cc104
-rw-r--r--o3d/plugin/cross/o3d_glue.h37
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