diff options
author | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-06 00:00:07 +0000 |
---|---|---|
committer | apatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-06 00:00:07 +0000 |
commit | 5aa6a312dc935c3392e025e97daded48f5363a05 (patch) | |
tree | 2c1a286841459eba6b8b38528e2a18057f03c9d4 | |
parent | 7bc4b5d06145e8753fdc8b2db04a5fb20ab86299 (diff) | |
download | chromium_src-5aa6a312dc935c3392e025e97daded48f5363a05.zip chromium_src-5aa6a312dc935c3392e025e97daded48f5363a05.tar.gz chromium_src-5aa6a312dc935c3392e025e97daded48f5363a05.tar.bz2 |
Reland r65152 with mac and linux fix.
Original review URL: http://codereview.chromium.org/3531008
TEST=try, ui_tests
BUG=none
Review URL: http://codereview.chromium.org/4545003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@65283 0039d316-1c4b-4281-b951-d872f2087c98
23 files changed, 417 insertions, 395 deletions
diff --git a/build/features_override.gypi b/build/features_override.gypi index 7c4b941..5c069ea 100644 --- a/build/features_override.gypi +++ b/build/features_override.gypi @@ -11,6 +11,7 @@ # but not listed below, it will revert to its hardcoded webkit value. 'feature_defines': [ 'ENABLE_3D_CANVAS=1', + 'ENABLE_3D_PLUGIN=1', 'ENABLE_BLOB=1', 'ENABLE_BLOB_SLICE=1', 'ENABLE_CHANNEL_MESSAGING=1', diff --git a/chrome/renderer/ggl/ggl.cc b/chrome/renderer/ggl/ggl.cc index 0589852..cfe6743 100644 --- a/chrome/renderer/ggl/ggl.cc +++ b/chrome/renderer/ggl/ggl.cc @@ -6,7 +6,6 @@ #include "base/ref_counted.h" #include "base/singleton.h" -#include "base/thread_local.h" #include "base/weak_ptr.h" #include "chrome/renderer/command_buffer_proxy.h" #include "chrome/renderer/ggl/ggl.h" @@ -35,8 +34,6 @@ const int32 kCommandBufferSize = 1024 * 1024; // creation attributes. const int32 kTransferBufferSize = 1024 * 1024; -base::ThreadLocalPointer<Context> g_current_context; - // Singleton used to initialize and terminate the gles2 library. class GLES2Initializer { public: @@ -77,7 +74,7 @@ class Context : public base::SupportsWeakPtr<Context> { // Provides a callback that will be invoked when SwapBuffers has completed // service side. - void SetSwapBuffersCallback(Callback1<Context*>::Type* callback) { + void SetSwapBuffersCallback(Callback0::Type* callback) { swap_buffers_callback_.reset(callback); } @@ -117,17 +114,22 @@ class Context : public base::SupportsWeakPtr<Context> { // TODO(gman): Remove this. void DisableShaderTranslation(); + gpu::gles2::GLES2Implementation* gles2_implementation() const { + return gles2_implementation_; + } private: void OnSwapBuffers(); scoped_refptr<GpuChannelHost> channel_; base::WeakPtr<Context> parent_; - scoped_ptr<Callback1<Context*>::Type> swap_buffers_callback_; + scoped_ptr<Callback0::Type> swap_buffers_callback_; uint32 parent_texture_id_; CommandBufferProxy* command_buffer_; gpu::gles2::GLES2CmdHelper* gles2_helper_; int32 transfer_buffer_id_; gpu::gles2::GLES2Implementation* gles2_implementation_; + gfx::Size size_; + Error last_error_; DISALLOW_COPY_AND_ASSIGN(Context); @@ -262,19 +264,25 @@ bool Context::Initialize(gfx::NativeViewId view, transfer_buffer_id_, false); + size_ = size; + return true; } #if defined(OS_MACOSX) void Context::ResizeOnscreen(const gfx::Size& size) { DCHECK(size.width() > 0 && size.height() > 0); + size_ = size; command_buffer_->SetWindowSize(size); } #endif void Context::ResizeOffscreen(const gfx::Size& size) { DCHECK(size.width() > 0 && size.height() > 0); - command_buffer_->ResizeOffscreenFrameBuffer(size); + if (size_ != size) { + command_buffer_->ResizeOffscreenFrameBuffer(size); + size_ = size; + } } uint32 Context::CreateParentTexture(const gfx::Size& size) const { @@ -343,7 +351,6 @@ void Context::Destroy() { } bool Context::MakeCurrent(Context* context) { - g_current_context.Set(context); if (context) { gles2::SetGLContext(context->gles2_implementation_); @@ -405,7 +412,7 @@ void Context::DisableShaderTranslation() { void Context::OnSwapBuffers() { if (swap_buffers_callback_.get()) - swap_buffers_callback_->Run(this); + swap_buffers_callback_->Run(); } #endif // ENABLE_GPU @@ -480,7 +487,7 @@ void DeleteParentTexture(Context* context, uint32 texture) { } void SetSwapBuffersCallback(Context* context, - Callback1<Context*>::Type* callback) { + Callback0::Type* callback) { #if defined(ENABLE_GPU) context->SetSwapBuffersCallback(callback); #endif @@ -494,14 +501,6 @@ bool MakeCurrent(Context* context) { #endif } -Context* GetCurrentContext() { -#if defined(ENABLE_GPU) - return g_current_context.Get(); -#else - return NULL; -#endif -} - bool SwapBuffers(Context* context) { #if defined(ENABLE_GPU) if (!context) @@ -518,9 +517,6 @@ bool DestroyContext(Context* context) { if (!context) return false; - if (context == GetCurrentContext()) - MakeCurrent(NULL); - delete context; return true; #else @@ -537,12 +533,8 @@ media::VideoDecodeContext* CreateVideoDecodeContext( return context->CreateVideoDecodeContext(message_loop, hardware_decoder); } -Error GetError() { +Error GetError(Context* context) { #if defined(ENABLE_GPU) - Context* context = GetCurrentContext(); - if (!context) - return BAD_CONTEXT; - return context->GetError(); #else return NOT_INITIALIZED; @@ -557,4 +549,12 @@ void DisableShaderTranslation(Context* context) { } #endif } + +gpu::gles2::GLES2Implementation* GetImplementation(Context* context) { + if (!context) + return NULL; + + return context->gles2_implementation(); +} + } // namespace ggl diff --git a/chrome/renderer/ggl/ggl.h b/chrome/renderer/ggl/ggl.h index 1d53f57..54a7f8e 100644 --- a/chrome/renderer/ggl/ggl.h +++ b/chrome/renderer/ggl/ggl.h @@ -18,6 +18,12 @@ class GpuChannelHost; class MessageLoop; +namespace gpu { +namespace gles2 { +class GLES2Implementation; +} +} + namespace media { class VideoDecodeContext; class VideoDecodeEngine; @@ -120,15 +126,11 @@ void DeleteParentTexture(Context* context, uint32 texture); // Provides a callback that will be invoked when SwapBuffers has completed // service side. -void SetSwapBuffersCallback(Context* context, - Callback1<Context*>::Type* callback); +void SetSwapBuffersCallback(Context* context, Callback0::Type* callback); // Set the current GGL context for the calling thread. bool MakeCurrent(Context* context); -// Get the calling thread's current GGL context. -Context* GetCurrentContext(); - // For a view context, display everything that has been rendered since the // last call. For an offscreen context, resolve everything that has been // rendered since the last call to a copy that can be accessed by the parent @@ -153,8 +155,12 @@ media::VideoDecodeContext* CreateVideoDecodeContext(Context* context, // TODO(gman): Remove this void DisableShaderTranslation(Context* context); +// Allows direct access to the GLES2 implementation so a context +// can be used without making it current. +gpu::gles2::GLES2Implementation* GetImplementation(Context* context); + // Return the current GGL error. -Error GetError(); +Error GetError(Context* context); } // namespace ggl diff --git a/chrome/renderer/pepper_plugin_delegate_impl.cc b/chrome/renderer/pepper_plugin_delegate_impl.cc index 06ca49a..d7b6c87 100644 --- a/chrome/renderer/pepper_plugin_delegate_impl.cc +++ b/chrome/renderer/pepper_plugin_delegate_impl.cc @@ -8,6 +8,7 @@ #include "app/l10n_util.h" #include "app/surface/transport_dib.h" +#include "base/callback.h" #include "base/file_path.h" #include "base/logging.h" #include "base/scoped_ptr.h" @@ -21,9 +22,13 @@ #include "chrome/common/render_messages_params.h" #include "chrome/renderer/audio_message_filter.h" #include "chrome/renderer/command_buffer_proxy.h" +#include "chrome/renderer/ggl/ggl.h" +#include "chrome/renderer/gpu_channel_host.h" #include "chrome/renderer/render_thread.h" #include "chrome/renderer/render_view.h" +#include "chrome/renderer/webgraphicscontext3d_command_buffer_impl.h" #include "chrome/renderer/webplugin_delegate_proxy.h" +#include "gfx/size.h" #include "grit/locale_settings.h" #include "ppapi/c/dev/pp_video_dev.h" #include "third_party/WebKit/WebKit/chromium/public/WebFileChooserCompletion.h" @@ -80,139 +85,29 @@ class PlatformImage2DImpl : public pepper::PluginDelegate::PlatformImage2D { class PlatformContext3DImpl : public pepper::PluginDelegate::PlatformContext3D { public: - explicit PlatformContext3DImpl(RenderView* render_view) - : render_view_(render_view), - nested_delegate_(NULL), - command_buffer_(NULL), - renderview_to_webplugin_adapter_(render_view) {} + explicit PlatformContext3DImpl(WebKit::WebView* web_view) + : web_view_(web_view), + context_(NULL) { + } virtual ~PlatformContext3DImpl() { - if (nested_delegate_) { - nested_delegate_->DestroyCommandBuffer(command_buffer_); - nested_delegate_->PluginDestroyed(); + if (context_) { + ggl::DestroyContext(context_); + context_ = NULL; } } - virtual bool Init(const gfx::Rect& position, const gfx::Rect& clip); - - virtual gpu::CommandBuffer* GetCommandBuffer() { - return command_buffer_; - } - - virtual void SetNotifyRepaintTask(Task* task) { - command_buffer_->SetNotifyRepaintTask(task); - } + virtual bool Init(); + virtual bool SwapBuffers(); + virtual unsigned GetError(); + virtual void SetSwapBuffersCallback(Callback0::Type* callback); + void ResizeBackingTexture(const gfx::Size& size); + virtual unsigned GetBackingTextureId(); + virtual gpu::gles2::GLES2Implementation* GetGLES2Implementation(); private: - - class WebPluginAdapter : public webkit_glue::WebPlugin { - public: - explicit WebPluginAdapter(RenderView* render_view) - : render_view_(render_view) {} - - virtual void SetWindow(gfx::PluginWindowHandle window) { - render_view_->CreatedPluginWindow(window); - } - - virtual void WillDestroyWindow(gfx::PluginWindowHandle window) { - render_view_->WillDestroyPluginWindow(window); - } - - virtual void SetAcceptsInputEvents(bool accepts) { - NOTREACHED(); - } - -#if defined(OS_WIN) - virtual void SetWindowlessPumpEvent(HANDLE pump_messages_event) { - NOTREACHED(); - } -#endif - - virtual void CancelResource(unsigned long id) { - NOTREACHED(); - } - - virtual void Invalidate() { - NOTREACHED(); - } - - virtual void InvalidateRect(const gfx::Rect& rect) { - NOTREACHED(); - } - - virtual NPObject* GetWindowScriptNPObject() { - NOTREACHED(); - return NULL; - } - - virtual NPObject* GetPluginElement() { - NOTREACHED(); - return NULL; - } - - virtual void SetCookie(const GURL& url, - const GURL& first_party_for_cookies, - const std::string& cookie) { - NOTREACHED(); - } - - virtual std::string GetCookies(const GURL& url, - const GURL& first_party_for_cookies) { - NOTREACHED(); - return std::string(); - } - - virtual void ShowModalHTMLDialog(const GURL& url, int width, int height, - const std::string& json_arguments, - std::string* json_retval) { - NOTREACHED(); - } - - virtual void OnMissingPluginStatus(int status) { - NOTREACHED(); - } - - virtual void HandleURLRequest(const char* url, - const char* method, - const char* target, - const char* buf, - unsigned int len, - int notify_id, - bool popups_allowed) { - NOTREACHED(); - } - - virtual void CancelDocumentLoad() { - NOTREACHED(); - } - - virtual void InitiateHTTPRangeRequest(const char* url, - const char* range_info, - int range_request_id) { - NOTREACHED(); - } - - virtual bool IsOffTheRecord() { - NOTREACHED(); - return false; - } - - virtual void SetDeferResourceLoading(unsigned long resource_id, - bool defer) { - NOTREACHED(); - } - - private: - RenderView* render_view_; - }; - - void SendNestedDelegateGeometryToBrowser(const gfx::Rect& window_rect, - const gfx::Rect& clip_rect); - - RenderView* render_view_; - WebPluginDelegateProxy* nested_delegate_; - CommandBufferProxy* command_buffer_; - WebPluginAdapter renderview_to_webplugin_adapter_; + WebKit::WebView* web_view_; + ggl::Context* context_; }; #endif // ENABLE_GPU @@ -278,76 +173,83 @@ class PlatformAudioImpl #ifdef ENABLE_GPU -bool PlatformContext3DImpl::Init(const gfx::Rect& position, - const gfx::Rect& clip) { -#if defined(ENABLE_GPU) +bool PlatformContext3DImpl::Init() { // Ignore initializing more than once. - if (nested_delegate_) + if (context_) return true; - // Create an instance of the GPU plugin that is responsible for 3D - // rendering. - nested_delegate_ = new WebPluginDelegateProxy( - std::string("application/vnd.google.chrome.gpu-plugin"), - render_view_->AsWeakPtr()); - - if (nested_delegate_->Initialize(GURL(), std::vector<std::string>(), - std::vector<std::string>(), - &renderview_to_webplugin_adapter_, - false)) { - // Ensure the window has the correct size before initializing the - // command buffer. - nested_delegate_->UpdateGeometry(position, clip); - - // Ask the GPU plugin to create a command buffer and return a proxy. - command_buffer_ = nested_delegate_->CreateCommandBuffer(); - if (command_buffer_) { - // Initialize the proxy command buffer. - if (command_buffer_->Initialize(kDefaultCommandBufferSize)) { -#if defined(OS_MACOSX) - command_buffer_->SetWindowSize(position.size()); -#endif // OS_MACOSX + WebGraphicsContext3DCommandBufferImpl* context = + static_cast<WebGraphicsContext3DCommandBufferImpl*>( + web_view_->graphicsContext3D()); + if (!context) + return false; - // Make sure the nested delegate shows up in the right place - // on the page. - SendNestedDelegateGeometryToBrowser(position, clip); + ggl::Context* parent_context = context->context(); + if (!parent_context) + return false; - return true; - } - } + RenderThread* render_thread = RenderThread::current(); + if (!render_thread) + return false; - nested_delegate_->DestroyCommandBuffer(command_buffer_); - command_buffer_ = NULL; - } + GpuChannelHost* host = render_thread->GetGpuChannel(); + if (!host) + return false; - nested_delegate_->PluginDestroyed(); - nested_delegate_ = NULL; -#endif // ENABLE_GPU - return false; + DCHECK(host->state() == GpuChannelHost::CONNECTED); + + // TODO(apatrick): Let Pepper plugins configure their back buffer surface. + static const int32 attribs[] = { + ggl::GGL_ALPHA_SIZE, 8, + ggl::GGL_DEPTH_SIZE, 24, + ggl::GGL_STENCIL_SIZE, 8, + ggl::GGL_SAMPLES, 0, + ggl::GGL_SAMPLE_BUFFERS, 0, + ggl::GGL_NONE, + }; + + // TODO(apatrick): Decide which extensions to expose to Pepper plugins. + // Currently they get only core GLES2. + context_ = ggl::CreateOffscreenContext(host, + parent_context, + gfx::Size(1, 1), + "", + attribs); + if (!context_) + return false; + + return true; } -void PlatformContext3DImpl::SendNestedDelegateGeometryToBrowser( - const gfx::Rect& window_rect, - const gfx::Rect& clip_rect) { - // Inform the browser about the location of the plugin on the page. - // It appears that initially the plugin does not get laid out correctly -- - // possibly due to lazy creation of the nested delegate. - if (!nested_delegate_ || - !nested_delegate_->GetPluginWindowHandle() || - !render_view_) { - return; - } +bool PlatformContext3DImpl::SwapBuffers() { + DCHECK(context_); + return ggl::SwapBuffers(context_); +} + +unsigned PlatformContext3DImpl::GetError() { + DCHECK(context_); + return ggl::GetError(context_); +} + +void PlatformContext3DImpl::ResizeBackingTexture(const gfx::Size& size) { + DCHECK(context_); + ggl::ResizeOffscreenContext(context_, size); +} + +void PlatformContext3DImpl::SetSwapBuffersCallback(Callback0::Type* callback) { + DCHECK(context_); + ggl::SetSwapBuffersCallback(context_, callback); +} + +unsigned PlatformContext3DImpl::GetBackingTextureId() { + DCHECK(context_); + return ggl::GetParentTextureId(context_); +} - webkit_glue::WebPluginGeometry geom; - geom.window = nested_delegate_->GetPluginWindowHandle(); - geom.window_rect = window_rect; - geom.clip_rect = clip_rect; - // Rects_valid must be true for this to work in the Gtk port; - // hopefully not having the cutout rects will not cause incorrect - // clipping. - geom.rects_valid = true; - geom.visible = true; - render_view_->DidMovePlugin(geom); +gpu::gles2::GLES2Implementation* + PlatformContext3DImpl::GetGLES2Implementation() { + DCHECK(context_); + return ggl::GetImplementation(context_); } #endif // ENABLE_GPU @@ -604,7 +506,7 @@ PepperPluginDelegateImpl::CreateImage2D(int width, int height) { pepper::PluginDelegate::PlatformContext3D* PepperPluginDelegateImpl::CreateContext3D() { #ifdef ENABLE_GPU - return new PlatformContext3DImpl(render_view_); + return new PlatformContext3DImpl(render_view_->webview()); #else return NULL; #endif diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 176b1ae..7355fae8 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -86,6 +86,7 @@ #include "chrome/renderer/user_script_idle_scheduler.h" #include "chrome/renderer/user_script_slave.h" #include "chrome/renderer/visitedlink_slave.h" +#include "chrome/renderer/webgraphicscontext3d_command_buffer_impl.h" #include "chrome/renderer/webplugin_delegate_pepper.h" #include "chrome/renderer/webplugin_delegate_proxy.h" #include "chrome/renderer/websharedworker_proxy.h" @@ -2628,14 +2629,19 @@ WebMediaPlayer* RenderView::createMediaPlayer( if (cmd_line->HasSwitch(switches::kEnableAcceleratedDecoding) && !cmd_line->HasSwitch(switches::kDisableAcceleratedCompositing)) { + WebGraphicsContext3DCommandBufferImpl* context = + static_cast<WebGraphicsContext3DCommandBufferImpl*>( + frame->view()->graphicsContext3D()); + if (!context) + return NULL; + // Add the hardware video decoder factory. - // TODO(hclam): This assumes that ggl::Context is set to current - // internally. I need to make it more explicit to get the context. - bool ret = frame->view()->graphicsContext3D()->makeContextCurrent(); + // TODO(hclam): This will cause the renderer process to crash on context + // lost. + bool ret = context->makeContextCurrent(); CHECK(ret) << "Failed to switch context"; - collection->AddFilter(new IpcVideoDecoder( - MessageLoop::current(), ggl::GetCurrentContext())); + MessageLoop::current(), context->context())); } WebApplicationCacheHostImpl* appcache_host = diff --git a/chrome/renderer/webgraphicscontext3d_command_buffer_impl.h b/chrome/renderer/webgraphicscontext3d_command_buffer_impl.h index 116bced..11369d7 100644 --- a/chrome/renderer/webgraphicscontext3d_command_buffer_impl.h +++ b/chrome/renderer/webgraphicscontext3d_command_buffer_impl.h @@ -368,6 +368,8 @@ class WebGraphicsContext3DCommandBufferImpl virtual void copyTextureToCompositor(unsigned texture, unsigned parent_texture); + ggl::Context* context() { return context_; } + private: // The GGL context we use for OpenGL rendering. ggl::Context* context_; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 8f0d96b..44f97e3 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -1511,11 +1511,6 @@ bool Texture::AllocateStorage(const gfx::Size& size, GLenum format) { DCHECK_NE(id_, 0u); ScopedGLErrorSuppressor suppressor(decoder_); ScopedTexture2DBinder binder(decoder_, id_); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri( - GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, // mip level diff --git a/gpu/demos/demos.gyp b/gpu/demos/demos.gyp index d205eea..bae7503 100644 --- a/gpu/demos/demos.gyp +++ b/gpu/demos/demos.gyp @@ -156,7 +156,6 @@ ['OS=="mac"', { 'action': [ '<(PRODUCT_DIR)/Chromium.app/Contents/MacOS/Chromium', - '--enable-gpu-plugin', '--register-pepper-plugins=' '<(PRODUCT_DIR)/$(PRODUCT_NAME).plugin;' 'pepper-application/x-gpu-demo', @@ -165,7 +164,6 @@ }, { # OS != "mac" 'action': [ '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)chrome<(EXECUTABLE_SUFFIX)', - '--enable-gpu-plugin', '--register-pepper-plugins=$(TargetPath);' 'pepper-application/x-gpu-demo', 'file://$(ProjectDir)pepper_gpu_demo.html', diff --git a/gpu/demos/framework/pepper.cc b/gpu/demos/framework/pepper.cc index 9bcf9b1..2d3d50b 100644 --- a/gpu/demos/framework/pepper.cc +++ b/gpu/demos/framework/pepper.cc @@ -35,32 +35,31 @@ class PluginInstance : public pp::Instance { } } - virtual void ViewChanged(const pp::Rect& position, const pp::Rect& /*clip*/) { - if (size_.IsEmpty() && !position.IsEmpty()) { - size_ = position.size(); - demo_->InitWindowSize(size_.width(), size_.height()); + virtual void DidChangeView(const pp::Rect& position, + const pp::Rect& /*clip*/) { + if (size_ == position.size()) + return; + + size_ = position.size(); + demo_->InitWindowSize(size_.width(), size_.height()); + + if (graphics_.is_null()) { graphics_ = pp::Graphics3D_Dev(*this, 0, NULL, NULL); - if (!graphics_.is_null()) { - graphics_.MakeCurrent(); - demo_->InitGL(); - pp::Graphics3D_Dev::ResetCurrent(); - - // TODO(neb): Remove this once the startup order bug (51842) is fixed. - if (true) - // if (demo_->IsAnimated()) - Animate(0); - else - Paint(); - } + if (graphics_.is_null()) + return; + + if (!pp::Instance::BindGraphics(graphics_)) + return; + + graphics_.MakeCurrent(); + demo_->InitGL(); + pp::Graphics3D_Dev::ResetCurrent(); } - } - virtual void Graphics3DContextLost() { - // TODO(neb): Replace this with the correct code once 53889 is fixed. - Paint(); -// pp::Rect fake_position(size_); -// size_ = pp::Size(); -// ViewChanged(fake_position, fake_position); + if (demo_->IsAnimated()) + Animate(0); + else + Paint(); } void Paint() { diff --git a/gpu/demos/pepper_gpu_demo.html b/gpu/demos/pepper_gpu_demo.html index 8be4e57..64d88f7 100644 --- a/gpu/demos/pepper_gpu_demo.html +++ b/gpu/demos/pepper_gpu_demo.html @@ -3,10 +3,10 @@ <title>Pepper GPU Demo</title> </head> -<body style="background-color:Silver"> +<body style="background-color:Silver; -webkit-perspective: 1000;"> <h1>Pepper GPU Demo</h1> -<object id="plugin" type="pepper-application/x-gpu-demo" width="512" height="512" /> - +<embed id="plugin" type="pepper-application/x-gpu-demo" width="512" height="512" style="position:absolute; top: 30px; -webkit-transform: rotateY(30deg);" /> +<p style="position:absolute; top: 256px;">Text on top</p> </body> </html> diff --git a/ppapi/cpp/instance.cc b/ppapi/cpp/instance.cc index d900c8a..86996d6 100644 --- a/ppapi/cpp/instance.cc +++ b/ppapi/cpp/instance.cc @@ -7,6 +7,7 @@ #include "ppapi/c/dev/ppp_printing_dev.h" #include "ppapi/c/ppb_instance.h" #include "ppapi/cpp/common.h" +#include "ppapi/cpp/dev/graphics_3d_dev.h" #include "ppapi/cpp/dev/scrollbar_dev.h" #include "ppapi/cpp/dev/widget_dev.h" #include "ppapi/cpp/graphics_2d.h" @@ -88,6 +89,13 @@ bool Instance::BindGraphics(const Graphics2D& graphics) { graphics.pp_resource())); } +bool Instance::BindGraphics(const Graphics3D_Dev& graphics) { + if (!ppb_instance_f) + return false; + return PPBoolToBool(ppb_instance_f->BindGraphics(pp_instance(), + graphics.pp_resource())); +} + bool Instance::IsFullFrame() { if (!ppb_instance_f) return false; diff --git a/ppapi/cpp/instance.h b/ppapi/cpp/instance.h index df09bb9..e0a5889 100644 --- a/ppapi/cpp/instance.h +++ b/ppapi/cpp/instance.h @@ -27,6 +27,7 @@ struct PP_InputEvent; namespace pp { class Graphics2D; +class Graphics3D_Dev; class ImageData; class Point; class Rect; @@ -89,6 +90,9 @@ class Instance { /** See PPB_Instance.BindGraphics. */ bool BindGraphics(const Graphics2D& graphics); + /** See PPB_Instance.BindGraphics. */ + bool BindGraphics(const Graphics3D_Dev& graphics); + /** See PPB_Instance.IsFullFrame. */ bool IsFullFrame(); diff --git a/webkit/glue/plugins/pepper_graphics_3d.cc b/webkit/glue/plugins/pepper_graphics_3d.cc index fa9c2ec1c..2dc4def 100644 --- a/webkit/glue/plugins/pepper_graphics_3d.cc +++ b/webkit/glue/plugins/pepper_graphics_3d.cc @@ -92,8 +92,8 @@ PP_Bool MakeCurrent(PP_Resource graphics3d) { } PP_Resource GetCurrentContext() { - Graphics3D* currentContext = Graphics3D::GetCurrent(); - return currentContext ? currentContext->GetReference() : 0; + Graphics3D* current_context = Graphics3D::GetCurrent(); + return current_context ? current_context->GetReference() : 0; } PP_Bool SwapBuffers(PP_Resource graphics3d) { @@ -102,8 +102,14 @@ PP_Bool SwapBuffers(PP_Resource graphics3d) { } uint32_t GetError() { - // TODO(neb): Figure out error checking. - return PP_GRAPHICS_3D_ERROR_SUCCESS; + // Technically, this should return the last error that occurred on the current + // thread, rather than an error associated with a particular context. + // TODO(apatrick): Fix this. + Graphics3D* current_context = Graphics3D::GetCurrent(); + if (!current_context) + return 0; + + return current_context->GetError(); } const PPB_Graphics3D_Dev ppb_graphics3d = { @@ -123,10 +129,8 @@ const PPB_Graphics3D_Dev ppb_graphics3d = { } // namespace Graphics3D::Graphics3D(PluginModule* module) - : Resource(module), - command_buffer_(NULL), - transfer_buffer_id_(0), - method_factory3d_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { + : Resource(module), + bound_instance_(NULL) { } const PPB_Graphics3D_Dev* Graphics3D::GetInterface() { @@ -154,103 +158,98 @@ bool Graphics3D::Init(PP_Instance instance_id, int32_t config, // Create and initialize the objects required to issue GLES2 calls. platform_context_.reset(instance->delegate()->CreateContext3D()); - if (!platform_context_.get()) + if (!platform_context_.get()) { + Destroy(); return false; + } - if (!platform_context_->Init(instance->position(), - instance->clip())) { - platform_context_.reset(); + if (!platform_context_->Init()) { + Destroy(); return false; } - command_buffer_ = platform_context_->GetCommandBuffer(); - gles2_helper_.reset(new gpu::gles2::GLES2CmdHelper(command_buffer_)); - gpu::Buffer buffer = command_buffer_->GetRingBuffer(); - if (gles2_helper_->Initialize(buffer.size)) { - transfer_buffer_id_ = - command_buffer_->CreateTransferBuffer(kTransferBufferSize); - gpu::Buffer transfer_buffer = - command_buffer_->GetTransferBuffer(transfer_buffer_id_); - if (transfer_buffer.ptr) { - gles2_implementation_.reset(new gpu::gles2::GLES2Implementation( - gles2_helper_.get(), - transfer_buffer.size, - transfer_buffer.ptr, - transfer_buffer_id_, - false)); - platform_context_->SetNotifyRepaintTask( - method_factory3d_.NewRunnableMethod(&Graphics3D::HandleRepaint, - instance_id)); - return true; - } + + gles2_implementation_ = platform_context_->GetGLES2Implementation(); + DCHECK(gles2_implementation_); + + return true; +} + +bool Graphics3D::BindToInstance(PluginInstance* new_instance) { + if (bound_instance_ == new_instance) + return true; // Rebinding the same device, nothing to do. + if (bound_instance_ && new_instance) + return false; // Can't change a bound device. + + if (new_instance) { + // Resize the backing texture to the size of the instance when it is bound. + platform_context_->ResizeBackingTexture(new_instance->position().size()); + + // This is a temporary hack. The SwapBuffers is issued to force the resize + // to take place before any subsequent rendering. This might lead to a + // partially rendered frame being displayed. It is also not thread safe + // since the SwapBuffers is written to the command buffer and that command + // buffer might be written to by another thread. + // TODO(apatrick): Figure out the semantics of binding and resizing. + platform_context_->SwapBuffers(); } - // Tear everything down if initialization failed. - Destroy(); - return false; + bound_instance_ = new_instance; + return true; } bool Graphics3D::MakeCurrent() { - if (!command_buffer_) + if (!platform_context_.get()) return false; CurrentContextKey::get()->Set(this); - // Don't request latest error status from service. Just use the locally - // cached information from the last flush. - // TODO(apatrick): I'm not sure if this should actually change the - // current context if it fails. For now it gets changed even if it fails - // becuase making GL calls with a NULL context crashes. - // TODO(neb): Figure out error checking. -// if (command_buffer_->GetCachedError() != gpu::error::kNoError) -// return false; + // TODO(apatrick): Return false on context lost. return true; } bool Graphics3D::SwapBuffers() { - if (!command_buffer_) + if (!platform_context_.get()) return false; - // Don't request latest error status from service. Just use the locally cached - // information from the last flush. - // TODO(neb): Figure out error checking. -// if (command_buffer_->GetCachedError() != gpu::error::kNoError) -// return false; + return platform_context_->SwapBuffers(); +} - gles2_implementation_->SwapBuffers(); - return true; +unsigned Graphics3D::GetError() { + if (!platform_context_.get()) + return 0; + + return platform_context_->GetError(); } -void Graphics3D::Destroy() { - if (GetCurrent() == this) { - ResetCurrent(); - } +void Graphics3D::ResizeBackingTexture(const gfx::Size& size) { + if (!platform_context_.get()) + return; - method_factory3d_.RevokeAll(); + platform_context_->ResizeBackingTexture(size); +} - gles2_implementation_.reset(); +void Graphics3D::SetSwapBuffersCallback(Callback0::Type* callback) { + if (!platform_context_.get()) + return; - if (command_buffer_ && transfer_buffer_id_ != 0) { - command_buffer_->DestroyTransferBuffer(transfer_buffer_id_); - transfer_buffer_id_ = 0; - } + platform_context_->SetSwapBuffersCallback(callback); +} - gles2_helper_.reset(); +unsigned Graphics3D::GetBackingTextureId() { + if (!platform_context_.get()) + return 0; - // Platform context owns the command buffer. - platform_context_.reset(); - command_buffer_ = NULL; + return platform_context_->GetBackingTextureId(); } -void Graphics3D::HandleRepaint(PP_Instance instance_id) { - PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id); - if (instance) { - instance->Graphics3DContextLost(); - if (platform_context_.get()) { - platform_context_->SetNotifyRepaintTask( - method_factory3d_.NewRunnableMethod(&Graphics3D::HandleRepaint, - instance_id)); - } +void Graphics3D::Destroy() { + if (GetCurrent() == this) { + ResetCurrent(); } + + gles2_implementation_ = NULL; + + platform_context_.reset(); } } // namespace pepper diff --git a/webkit/glue/plugins/pepper_graphics_3d.h b/webkit/glue/plugins/pepper_graphics_3d.h index 96c7b80..5c00068 100644 --- a/webkit/glue/plugins/pepper_graphics_3d.h +++ b/webkit/glue/plugins/pepper_graphics_3d.h @@ -5,19 +5,19 @@ #ifndef WEBKIT_GLUE_PLUGINS_PEPPER_GRAPHICS_3D_H_ #define WEBKIT_GLUE_PLUGINS_PEPPER_GRAPHICS_3D_H_ +#include "base/callback.h" #include "base/scoped_ptr.h" +#include "gfx/size.h" #include "gpu/command_buffer/client/gles2_cmd_helper.h" #include "gpu/command_buffer/client/gles2_implementation.h" #include "ppapi/c/pp_instance.h" #include "webkit/glue/plugins/pepper_plugin_delegate.h" #include "webkit/glue/plugins/pepper_resource.h" -namespace gfx { -class Rect; -} // namespace gfx - namespace gpu { -class CommandBuffer; +namespace gles2 { +class GLES2Implementation; +} } // namespace gpu struct PPB_Graphics3D_Dev; @@ -48,35 +48,40 @@ class Graphics3D : public Resource { bool Init(PP_Instance instance_id, int32_t config, const int32_t* attrib_list); + // Associates this Graphics3D with the given plugin instance. You can pass + // NULL to clear the existing device. Returns true on success. In this case, + // the last rendered frame is displayed. + // TODO(apatrick): Figure out the best semantics here. + bool BindToInstance(PluginInstance* new_instance); + bool MakeCurrent(); bool SwapBuffers(); + unsigned GetError(); + + void ResizeBackingTexture(const gfx::Size& size); + + void SetSwapBuffersCallback(Callback0::Type* callback); + + unsigned GetBackingTextureId(); + gpu::gles2::GLES2Implementation* impl() { - return gles2_implementation_.get(); + return gles2_implementation_; } private: - void HandleRepaint(PP_Instance instance_id); void Destroy(); + // Non-owning pointer to the plugin instance this context is currently bound + // to, if any. If the context is currently unbound, this will be NULL. + PluginInstance* bound_instance_; + // PluginDelegate's 3D Context. Responsible for providing the command buffer. scoped_ptr<PluginDelegate::PlatformContext3D> platform_context_; - // Command buffer is owned by the platform context. - gpu::CommandBuffer* command_buffer_; - - // GLES2 Command Helper instance. - scoped_ptr<gpu::gles2::GLES2CmdHelper> gles2_helper_; - - // ID of the transfer buffer. - int32_t transfer_buffer_id_; - - // GLES2 Implementation instance. - scoped_ptr<gpu::gles2::GLES2Implementation> gles2_implementation_; - - // Runnable methods that must be cancelled when the 3D context is destroyed. - ScopedRunnableMethodFactory<Graphics3D> method_factory3d_; + // GLES2 Implementation instance. Owned by the platform context's GGL context. + gpu::gles2::GLES2Implementation* gles2_implementation_; }; } // namespace pepper diff --git a/webkit/glue/plugins/pepper_plugin_delegate.h b/webkit/glue/plugins/pepper_plugin_delegate.h index 0998355..d2c67c7 100644 --- a/webkit/glue/plugins/pepper_plugin_delegate.h +++ b/webkit/glue/plugins/pepper_plugin_delegate.h @@ -13,6 +13,7 @@ #include "base/shared_memory.h" #include "base/sync_socket.h" #include "base/task.h" +#include "gfx/size.h" #include "googleurl/src/gurl.h" #include "ppapi/c/pp_completion_callback.h" #include "ppapi/c/pp_errors.h" @@ -37,7 +38,9 @@ class Rect; } namespace gpu { -class CommandBuffer; +namespace gles2 { +class GLES2Implementation; +} } namespace skia { @@ -87,14 +90,30 @@ class PluginDelegate { virtual ~PlatformContext3D() {} // Initialize the context. - virtual bool Init(const gfx::Rect& position, const gfx::Rect& clip) = 0; + virtual bool Init() = 0; + + // Present the rendered frame to the compositor. + virtual bool SwapBuffers() = 0; + + // Get the last EGL error. + virtual unsigned GetError() = 0; + + // Resize the backing texture used as a back buffer by OpenGL. + virtual void ResizeBackingTexture(const gfx::Size& size) = 0; + + // Set an optional callback that will be invoked when the side effects of + // a SwapBuffers call become visible to the compositor. Takes ownership + // of the callback. + virtual void SetSwapBuffersCallback(Callback0::Type* callback) = 0; - // This call will return the address of the command buffer object that is - // constructed in Initialize() and is valid until this context is destroyed. - virtual gpu::CommandBuffer* GetCommandBuffer() = 0; + // If the plugin instance is backed by an OpenGL, return its ID in the + // compositors namespace. Otherwise return 0. Returns 0 by default. + virtual unsigned GetBackingTextureId() = 0; - // Sets the function to be called on repaint. - virtual void SetNotifyRepaintTask(Task* task) = 0; + // This call will return the address of the GLES2 implementation for this + // context that is constructed in Initialize() and is valid until this + // context is destroyed. + virtual gpu::gles2::GLES2Implementation* GetGLES2Implementation() = 0; }; class PlatformAudio { diff --git a/webkit/glue/plugins/pepper_plugin_instance.cc b/webkit/glue/plugins/pepper_plugin_instance.cc index 31ef4da..8a20e74 100644 --- a/webkit/glue/plugins/pepper_plugin_instance.cc +++ b/webkit/glue/plugins/pepper_plugin_instance.cc @@ -50,6 +50,7 @@ #include "webkit/glue/plugins/pepper_buffer.h" #include "webkit/glue/plugins/pepper_common.h" #include "webkit/glue/plugins/pepper_graphics_2d.h" +#include "webkit/glue/plugins/pepper_graphics_3d.h" #include "webkit/glue/plugins/pepper_event_conversion.h" #include "webkit/glue/plugins/pepper_fullscreen_container.h" #include "webkit/glue/plugins/pepper_image_data.h" @@ -161,11 +162,11 @@ PP_Var GetOwnerElementObject(PP_Instance instance_id) { return instance->GetOwnerElementObject(); } -PP_Bool BindGraphics(PP_Instance instance_id, PP_Resource device_id) { +PP_Bool BindGraphics(PP_Instance instance_id, PP_Resource graphics_id) { PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id); if (!instance) return PP_FALSE; - return BoolToPPBool(instance->BindGraphics(device_id)); + return BoolToPPBool(instance->BindGraphics(graphics_id)); } PP_Bool IsFullFrame(PP_Instance instance_id) { @@ -339,8 +340,8 @@ const PPB_Zoom_Dev* PluginInstance::GetZoomInterface() { void PluginInstance::Paint(WebCanvas* canvas, const gfx::Rect& plugin_rect, const gfx::Rect& paint_rect) { - if (bound_graphics_2d_) - bound_graphics_2d_->Paint(canvas, plugin_rect, paint_rect); + if (bound_graphics_2d()) + bound_graphics_2d()->Paint(canvas, plugin_rect, paint_rect); } void PluginInstance::InvalidateRect(const gfx::Rect& rect) { @@ -373,6 +374,17 @@ void PluginInstance::ScrollRect(int dx, int dy, const gfx::Rect& rect) { } } +unsigned PluginInstance::GetBackingTextureId() { + if (!bound_graphics_3d()) + return 0; + + return bound_graphics_3d()->GetBackingTextureId(); +} + +void PluginInstance::CommitBackingTexture() { + container_->commitBackingTexture(); +} + PP_Var PluginInstance::GetWindowObject() { if (!container_) return PP_MakeUndefined(); @@ -391,35 +403,44 @@ PP_Var PluginInstance::GetOwnerElementObject() { container_->scriptableObjectForElement()); } -bool PluginInstance::BindGraphics(PP_Resource device_id) { - if (!device_id) { +bool PluginInstance::BindGraphics(PP_Resource graphics_id) { + if (!graphics_id) { // Special-case clearing the current device. - if (bound_graphics_2d_) { - bound_graphics_2d_->BindToInstance(NULL); - bound_graphics_2d_ = NULL; + if (bound_graphics_.get()) { + if (bound_graphics_2d()) { + bound_graphics_2d()->BindToInstance(NULL); + } else if (bound_graphics_.get()) { + bound_graphics_3d()->SetSwapBuffersCallback(NULL); + bound_graphics_3d()->BindToInstance(NULL); + } InvalidateRect(gfx::Rect()); } + bound_graphics_ = NULL; return true; } - scoped_refptr<Graphics2D> device_2d = Resource::GetAs<Graphics2D>(device_id); + scoped_refptr<Graphics2D> graphics_2d = + Resource::GetAs<Graphics2D>(graphics_id); + scoped_refptr<Graphics3D> graphics_3d = + Resource::GetAs<Graphics3D>(graphics_id); - if (device_2d) { - if (!device_2d->BindToInstance(this)) + if (graphics_2d) { + if (!graphics_2d->BindToInstance(this)) return false; // Can't bind to more than one instance. + bound_graphics_ = graphics_2d; // See http://crbug.com/49403: this can be further optimized by keeping the // old device around and painting from it. - if (bound_graphics_2d_.get()) { + if (bound_graphics_2d()) { // Start the new image with the content of the old image until the plugin // repaints. const SkBitmap* old_backing_bitmap = - bound_graphics_2d_->image_data()->GetMappedBitmap(); + bound_graphics_2d()->image_data()->GetMappedBitmap(); SkRect old_size = SkRect::MakeWH( SkScalar(static_cast<float>(old_backing_bitmap->width())), SkScalar(static_cast<float>(old_backing_bitmap->height()))); - SkCanvas canvas(*device_2d->image_data()->GetMappedBitmap()); + SkCanvas canvas(*graphics_2d->image_data()->GetMappedBitmap()); canvas.drawBitmap(*old_backing_bitmap, 0, 0); // Fill in any extra space with white. @@ -427,8 +448,14 @@ bool PluginInstance::BindGraphics(PP_Resource device_id) { canvas.drawARGB(255, 255, 255, 255); } - bound_graphics_2d_ = device_2d; // BindToInstance will have invalidated the plugin if necessary. + } else if (graphics_3d) { + if (!graphics_3d->BindToInstance(this)) + return false; + + bound_graphics_ = graphics_3d; + bound_graphics_3d()->SetSwapBuffersCallback( + NewCallback(this, &PluginInstance::CommitBackingTexture)); } return true; @@ -538,7 +565,17 @@ PP_Var PluginInstance::GetInstanceObject() { void PluginInstance::ViewChanged(const gfx::Rect& position, const gfx::Rect& clip) { + if (position.size() != position_.size() && bound_graphics_3d()) { + // TODO(apatrick): This is a hack to force the back buffer to resize. + // It is obviously wrong to call SwapBuffers when a partial frame has + // potentially been rendered. Plan is to embed resize commands in the + // command buffer just before ViewChanged is called. + bound_graphics_3d()->ResizeBackingTexture(position.size()); + bound_graphics_3d()->SwapBuffers(); + } + position_ = position; + if (clip.IsEmpty()) { // WebKit can give weird (x,y) positions for empty clip rects (since the // position technically doesn't matter). But we want to make these @@ -580,13 +617,13 @@ void PluginInstance::SetContentAreaFocus(bool has_focus) { } void PluginInstance::ViewInitiatedPaint() { - if (bound_graphics_2d_) - bound_graphics_2d_->ViewInitiatedPaint(); + if (bound_graphics_2d()) + bound_graphics_2d()->ViewInitiatedPaint(); } void PluginInstance::ViewFlushedPaint() { - if (bound_graphics_2d_) - bound_graphics_2d_->ViewFlushedPaint(); + if (bound_graphics_2d()) + bound_graphics_2d()->ViewFlushedPaint(); } bool PluginInstance::GetBitmapForOptimizedPluginPaint( @@ -596,13 +633,13 @@ bool PluginInstance::GetBitmapForOptimizedPluginPaint( gfx::Rect* clip) { if (!always_on_top_) return false; - if (!bound_graphics_2d_ || !bound_graphics_2d_->is_always_opaque()) + if (!bound_graphics_2d() || !bound_graphics_2d()->is_always_opaque()) return false; // We specifically want to compare against the area covered by the backing // store when seeing if we cover the given paint bounds, since the backing // store could be smaller than the declared plugin area. - ImageData* image_data = bound_graphics_2d_->image_data(); + ImageData* image_data = bound_graphics_2d()->image_data(); gfx::Rect plugin_backing_store_rect(position_.origin(), gfx::Size(image_data->width(), image_data->height())); @@ -838,16 +875,6 @@ void PluginInstance::PrintEnd() { #endif // defined(OS_LINUX) } -void PluginInstance::Graphics3DContextLost() { - if (!plugin_graphics_3d_interface_) { - plugin_graphics_3d_interface_ = - reinterpret_cast<const PPP_Graphics3D_Dev*>(module_->GetPluginInterface( - PPP_GRAPHICS_3D_DEV_INTERFACE)); - } - if (plugin_graphics_3d_interface_) - plugin_graphics_3d_interface_->Graphics3DContextLost(pp_instance()); -} - bool PluginInstance::IsFullscreen() { return fullscreen_container_ != NULL; } @@ -1118,5 +1145,18 @@ void PluginInstance::DrawSkBitmapToCanvas( } #endif // defined(OS_MACOSX) +Graphics2D* PluginInstance::bound_graphics_2d() const { + if (bound_graphics_.get() == NULL) + return NULL; + + return bound_graphics_->Cast<Graphics2D>(); +} + +Graphics3D* PluginInstance::bound_graphics_3d() const { + if (bound_graphics_.get() == NULL) + return NULL; + + return bound_graphics_->Cast<Graphics3D>(); +} } // namespace pepper diff --git a/webkit/glue/plugins/pepper_plugin_instance.h b/webkit/glue/plugins/pepper_plugin_instance.h index c348f66..4ee92b7 100644 --- a/webkit/glue/plugins/pepper_plugin_instance.h +++ b/webkit/glue/plugins/pepper_plugin_instance.h @@ -48,9 +48,11 @@ class WebPluginContainer; namespace pepper { class Graphics2D; +class Graphics3D; class ImageData; class PluginDelegate; class PluginModule; +class Resource; class URLLoader; class FullscreenContainer; @@ -105,10 +107,18 @@ class PluginInstance : public base::RefCounted<PluginInstance> { // slow path can also be triggered if there is an overlapping frame. void ScrollRect(int dx, int dy, const gfx::Rect& rect); + // If the plugin instance is backed by a texture, return its texture ID in the + // compositor's namespace. Otherwise return 0. Returns 0 by default. + virtual unsigned GetBackingTextureId(); + + // Commit the backing texture to the screen once the side effects some + // rendering up to an offscreen SwapBuffers are visible. + void CommitBackingTexture(); + // PPB_Instance implementation. PP_Var GetWindowObject(); PP_Var GetOwnerElementObject(); - bool BindGraphics(PP_Resource device_id); + bool BindGraphics(PP_Resource graphics_id); bool full_frame() const { return full_frame_; } bool SetCursor(PP_CursorType_Dev type); PP_Var ExecuteScript(PP_Var script, PP_Var* exception); @@ -195,6 +205,14 @@ class PluginInstance : public base::RefCounted<PluginInstance> { const gfx::Rect& dest_rect, int canvas_height); #endif // OS_MACOSX + // Get the bound graphics context as a concrete 2D graphics context or returns + // null if the context is not 2D. + Graphics2D* bound_graphics_2d() const; + + // Get the bound graphics context as a concrete 3D graphics context or returns + // null if the context is not 3D. + Graphics3D* bound_graphics_3d() const; + PluginDelegate* delegate_; scoped_refptr<PluginModule> module_; const PPP_Instance* instance_interface_; @@ -218,6 +236,9 @@ class PluginInstance : public base::RefCounted<PluginInstance> { // be (0, 0, w, h) regardless of scroll position. gfx::Rect clip_; + // The current device context for painting in 2D or 3D. + scoped_refptr<Resource> bound_graphics_; + // We track two types of focus, one from WebKit, which is the focus among // all elements of the page, one one from the browser, which is whether the // tab/window has focus. We tell the plugin it has focus only when both of @@ -225,9 +246,6 @@ class PluginInstance : public base::RefCounted<PluginInstance> { bool has_webkit_focus_; bool has_content_area_focus_; - // The current device context for painting in 2D. - scoped_refptr<Graphics2D> bound_graphics_2d_; - // The id of the current find operation, or -1 if none is in process. int find_identifier_; diff --git a/webkit/glue/plugins/pepper_webplugin_impl.cc b/webkit/glue/plugins/pepper_webplugin_impl.cc index 0fa6cdb..8da398f 100644 --- a/webkit/glue/plugins/pepper_webplugin_impl.cc +++ b/webkit/glue/plugins/pepper_webplugin_impl.cc @@ -109,6 +109,10 @@ void WebPluginImpl::updateGeometry( instance_->ViewChanged(plugin_rect_, clip_rect); } +unsigned WebPluginImpl::getBackingTextureId() { + return instance_->GetBackingTextureId(); +} + void WebPluginImpl::updateFocus(bool focused) { instance_->SetWebKitFocus(focused); } diff --git a/webkit/glue/plugins/pepper_webplugin_impl.h b/webkit/glue/plugins/pepper_webplugin_impl.h index 15ee784..8922143 100644 --- a/webkit/glue/plugins/pepper_webplugin_impl.h +++ b/webkit/glue/plugins/pepper_webplugin_impl.h @@ -46,6 +46,7 @@ class WebPluginImpl : public WebKit::WebPlugin { const WebKit::WebRect& clip_rect, const WebKit::WebVector<WebKit::WebRect>& cut_outs_rects, bool is_visible); + virtual unsigned getBackingTextureId(); virtual void updateFocus(bool focused); virtual void updateVisibility(bool visible); virtual bool acceptsInputEvents(); diff --git a/webkit/glue/plugins/plugin_instance.cc b/webkit/glue/plugins/plugin_instance.cc index df949d0..b271e4d 100644 --- a/webkit/glue/plugins/plugin_instance.cc +++ b/webkit/glue/plugins/plugin_instance.cc @@ -178,6 +178,11 @@ void PluginInstance::DidFinishLoadWithReason( NPP_URLNotify(url.spec().c_str(), reason, notify_data); } +unsigned PluginInstance::GetBackingTextureId() { + // By default the plugin instance is not backed by an OpenGL texture. + return 0; +} + // NPAPI methods NPError PluginInstance::NPP_New(unsigned short mode, short argc, diff --git a/webkit/glue/plugins/plugin_instance.h b/webkit/glue/plugins/plugin_instance.h index 0dd3ee4..c853bfa 100644 --- a/webkit/glue/plugins/plugin_instance.h +++ b/webkit/glue/plugins/plugin_instance.h @@ -161,6 +161,10 @@ class PluginInstance : public base::RefCountedThreadSafe<PluginInstance> { bool use_mozilla_user_agent() { return use_mozilla_user_agent_; } void set_use_mozilla_user_agent() { use_mozilla_user_agent_ = true; } + // If the plugin instance is backed by a texture, return its ID in the + // compositor's namespace. Otherwise return 0. Returns 0 by default. + virtual unsigned GetBackingTextureId(); + // Helper that implements NPN_PluginThreadAsyncCall semantics void PluginThreadAsyncCall(void (*func)(void *), void *userData); diff --git a/webkit/glue/plugins/webplugin_impl.cc b/webkit/glue/plugins/webplugin_impl.cc index d033eb3..80774ff 100644 --- a/webkit/glue/plugins/webplugin_impl.cc +++ b/webkit/glue/plugins/webplugin_impl.cc @@ -327,6 +327,11 @@ void WebPluginImpl::updateGeometry( first_geometry_update_ = false; } +unsigned WebPluginImpl::getBackingTextureId() { + // Regular plugins do not have a backing texture. + return 0; +} + void WebPluginImpl::updateFocus(bool focused) { if (accepts_input_events_) delegate_->SetFocus(focused); diff --git a/webkit/glue/plugins/webplugin_impl.h b/webkit/glue/plugins/webplugin_impl.h index cb0970b..58289d6 100644 --- a/webkit/glue/plugins/webplugin_impl.h +++ b/webkit/glue/plugins/webplugin_impl.h @@ -73,6 +73,7 @@ class WebPluginImpl : public WebPlugin, virtual void updateGeometry( const WebKit::WebRect& frame_rect, const WebKit::WebRect& clip_rect, const WebKit::WebVector<WebKit::WebRect>& cut_outs, bool is_visible); + virtual unsigned getBackingTextureId(); virtual void updateFocus(bool focused); virtual void updateVisibility(bool visible); virtual bool acceptsInputEvents(); |