diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-18 16:51:44 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-18 16:51:44 +0000 |
commit | 2cff005220a16c7d1f814d5495887823b634f077 (patch) | |
tree | 867b327f3272f0d4f9cc3bbe085f1c28b30c3905 /content/renderer/render_widget_fullscreen_pepper.cc | |
parent | 21fcf83c508704a5bd11ed0467fc20b5e03f3acc (diff) | |
download | chromium_src-2cff005220a16c7d1f814d5495887823b634f077.zip chromium_src-2cff005220a16c7d1f814d5495887823b634f077.tar.gz chromium_src-2cff005220a16c7d1f814d5495887823b634f077.tar.bz2 |
Move render_widget files to content.
TBR=avi
Review URL: http://codereview.chromium.org/6709032
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@78703 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/renderer/render_widget_fullscreen_pepper.cc')
-rw-r--r-- | content/renderer/render_widget_fullscreen_pepper.cc | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc new file mode 100644 index 0000000..128129b --- /dev/null +++ b/content/renderer/render_widget_fullscreen_pepper.cc @@ -0,0 +1,395 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/renderer/render_widget_fullscreen_pepper.h" + +#include "chrome/common/render_messages.h" +#include "chrome/renderer/render_thread.h" +#include "content/renderer/ggl.h" +#include "content/renderer/gpu_channel_host.h" +#include "content/renderer/pepper_platform_context_3d_impl.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebWidget.h" +#include "webkit/plugins/ppapi/plugin_delegate.h" +#include "webkit/plugins/ppapi/ppapi_plugin_instance.h" + +using WebKit::WebCanvas; +using WebKit::WebCompositionUnderline; +using WebKit::WebCursorInfo; +using WebKit::WebInputEvent; +using WebKit::WebRect; +using WebKit::WebSize; +using WebKit::WebString; +using WebKit::WebTextDirection; +using WebKit::WebTextInputType; +using WebKit::WebVector; +using WebKit::WebWidget; + +namespace { + +// WebWidget that simply wraps the pepper plugin. +class PepperWidget : public WebWidget { + public: + PepperWidget(webkit::ppapi::PluginInstance* plugin, + RenderWidgetFullscreenPepper* widget) + : plugin_(plugin), + widget_(widget), + cursor_(WebCursorInfo::TypePointer) { + } + + // WebWidget API + virtual void close() { + delete this; + } + + virtual WebSize size() { + return size_; + } + + virtual void resize(const WebSize& size) { + size_ = size; + WebRect plugin_rect(0, 0, size_.width, size_.height); + plugin_->ViewChanged(plugin_rect, plugin_rect); + widget_->Invalidate(); + } + + virtual void animate() { + } + + virtual void layout() { + } + + virtual void paint(WebCanvas* canvas, const WebRect& rect) { + WebRect plugin_rect(0, 0, size_.width, size_.height); + plugin_->Paint(canvas, plugin_rect, rect); + } + + virtual void composite(bool finish) { + ggl::Context* context = widget_->context(); + DCHECK(context); + gpu::gles2::GLES2Implementation* gl = ggl::GetImplementation(context); + unsigned int texture = plugin_->GetBackingTextureId(); + gl->BindTexture(GL_TEXTURE_2D, texture); + gl->DrawArrays(GL_TRIANGLES, 0, 3); + ggl::SwapBuffers(context); + } + + virtual void themeChanged() { + NOTIMPLEMENTED(); + } + + virtual bool handleInputEvent(const WebInputEvent& event) { + return plugin_->HandleInputEvent(event, &cursor_); + } + + virtual void mouseCaptureLost() { + NOTIMPLEMENTED(); + } + + virtual void setFocus(bool focus) { + NOTIMPLEMENTED(); + } + + // TODO(piman): figure out IME and implement these if necessary. + virtual bool setComposition( + const WebString& text, + const WebVector<WebCompositionUnderline>& underlines, + int selectionStart, + int selectionEnd) { + return false; + } + + virtual bool confirmComposition() { + return false; + } + + virtual bool confirmComposition(const WebString& text) { + return false; + } + + virtual WebTextInputType textInputType() { + return WebKit::WebTextInputTypeNone; + } + + virtual WebRect caretOrSelectionBounds() { + return WebRect(); + } + + virtual void setTextDirection(WebTextDirection) { + } + + virtual bool isAcceleratedCompositingActive() const { + return widget_->context() && (plugin_->GetBackingTextureId() != 0); + } + + private: + scoped_refptr<webkit::ppapi::PluginInstance> plugin_; + RenderWidgetFullscreenPepper* widget_; + WebSize size_; + WebCursorInfo cursor_; + + DISALLOW_COPY_AND_ASSIGN(PepperWidget); +}; + +} // anonymous namespace + +// static +RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create( + int32 opener_id, RenderThreadBase* render_thread, + webkit::ppapi::PluginInstance* plugin) { + DCHECK_NE(MSG_ROUTING_NONE, opener_id); + scoped_refptr<RenderWidgetFullscreenPepper> widget( + new RenderWidgetFullscreenPepper(render_thread, plugin)); + widget->Init(opener_id); + return widget.release(); +} + +RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper( + RenderThreadBase* render_thread, + webkit::ppapi::PluginInstance* plugin) + : RenderWidgetFullscreen(render_thread), + plugin_(plugin), + context_(NULL), + buffer_(0), + program_(0) { +} + +RenderWidgetFullscreenPepper::~RenderWidgetFullscreenPepper() { + DestroyContext(); +} + +void RenderWidgetFullscreenPepper::Invalidate() { + InvalidateRect(gfx::Rect(size_.width(), size_.height())); +} + +void RenderWidgetFullscreenPepper::InvalidateRect(const WebKit::WebRect& rect) { + if (CheckCompositing()) { + scheduleComposite(); + } else { + didInvalidateRect(rect); + } +} + +void RenderWidgetFullscreenPepper::ScrollRect( + int dx, int dy, const WebKit::WebRect& rect) { + if (CheckCompositing()) { + scheduleComposite(); + } else { + didScrollRect(dx, dy, rect); + } +} + +void RenderWidgetFullscreenPepper::Destroy() { + // This function is called by the plugin instance as it's going away, so reset + // plugin_ to NULL to avoid calling into a dangling pointer e.g. on Close(). + plugin_ = NULL; + Send(new ViewHostMsg_Close(routing_id_)); +} + +webkit::ppapi::PluginDelegate::PlatformContext3D* +RenderWidgetFullscreenPepper::CreateContext3D() { + if (!context_) { + CreateContext(); + } + if (!context_) + return NULL; + return new PlatformContext3DImpl(context_); +} + +void RenderWidgetFullscreenPepper::DidInitiatePaint() { + if (plugin_) + plugin_->ViewInitiatedPaint(); +} + +void RenderWidgetFullscreenPepper::DidFlushPaint() { + if (plugin_) + plugin_->ViewFlushedPaint(); +} + +void RenderWidgetFullscreenPepper::Close() { + // If the fullscreen window is closed (e.g. user pressed escape), reset to + // normal mode. + if (plugin_) + plugin_->SetFullscreen(false, false); +} + +webkit::ppapi::PluginInstance* +RenderWidgetFullscreenPepper::GetBitmapForOptimizedPluginPaint( + const gfx::Rect& paint_bounds, + TransportDIB** dib, + gfx::Rect* location, + gfx::Rect* clip) { + if (plugin_ && + plugin_->GetBitmapForOptimizedPluginPaint(paint_bounds, dib, + location, clip)) + return plugin_; + return NULL; +} + +void RenderWidgetFullscreenPepper::OnResize(const gfx::Size& size, + const gfx::Rect& resizer_rect) { + if (context_) { + gpu::gles2::GLES2Implementation* gl = ggl::GetImplementation(context_); +#if defined(OS_MACOSX) + ggl::ResizeOnscreenContext(context_, size); +#else + gl->ResizeCHROMIUM(size.width(), size.height()); +#endif + gl->Viewport(0, 0, size.width(), size.height()); + } + RenderWidget::OnResize(size, resizer_rect); +} + +WebWidget* RenderWidgetFullscreenPepper::CreateWebWidget() { + return new PepperWidget(plugin_, this); +} + +void RenderWidgetFullscreenPepper::CreateContext() { + DCHECK(!context_); + RenderThread* render_thread = RenderThread::current(); + DCHECK(render_thread); + GpuChannelHost* host = render_thread->EstablishGpuChannelSync(); + if (!host) + return; + const int32 attribs[] = { + ggl::GGL_ALPHA_SIZE, 8, + ggl::GGL_DEPTH_SIZE, 0, + ggl::GGL_STENCIL_SIZE, 0, + ggl::GGL_SAMPLES, 0, + ggl::GGL_SAMPLE_BUFFERS, 0, + ggl::GGL_NONE, + }; + context_ = ggl::CreateViewContext( + host, + routing_id(), + "GL_OES_packed_depth_stencil GL_OES_depth24", + attribs); + if (!context_ || !InitContext()) { + DestroyContext(); + return; + } + ggl::SetSwapBuffersCallback( + context_, + NewCallback(this, &RenderWidgetFullscreenPepper::DidFlushPaint)); +} + +void RenderWidgetFullscreenPepper::DestroyContext() { + if (context_) { + gpu::gles2::GLES2Implementation* gl = ggl::GetImplementation(context_); + if (program_) { + gl->DeleteProgram(program_); + program_ = 0; + } + if (buffer_) { + gl->DeleteBuffers(1, &buffer_); + buffer_ = 0; + } + ggl::DestroyContext(context_); + context_ = NULL; + } +} + +namespace { + +const char kVertexShader[] = + "attribute vec2 in_tex_coord;\n" + "varying vec2 tex_coord;\n" + "void main() {\n" + " gl_Position = vec4(in_tex_coord.x * 2. - 1.,\n" + " in_tex_coord.y * 2. - 1.,\n" + " 0.,\n" + " 1.);\n" + " tex_coord = vec2(in_tex_coord.x, in_tex_coord.y);\n" + "}\n"; + +const char kFragmentShader[] = + "precision mediump float;\n" + "varying vec2 tex_coord;\n" + "uniform sampler2D in_texture;\n" + "void main() {\n" + " gl_FragColor = texture2D(in_texture, tex_coord);\n" + "}\n"; + +GLuint CreateShaderFromSource(gpu::gles2::GLES2Implementation* gl, + GLenum type, + const char* source) { + GLuint shader = gl->CreateShader(type); + gl->ShaderSource(shader, 1, &source, NULL); + gl->CompileShader(shader); + int status; + gl->GetShaderiv(shader, GL_COMPILE_STATUS, &status); + if (!status) { + int size = 0; + gl->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &size); + scoped_array<char> log(new char[size]); + gl->GetShaderInfoLog(shader, size, NULL, log.get()); + DLOG(ERROR) << "Compilation failed: " << log.get(); + gl->DeleteShader(shader); + shader = 0; + } + return shader; +} + +const float kTexCoords[] = { + 0.f, 0.f, + 0.f, 2.f, + 2.f, 0.f, +}; + +} // anonymous namespace + +bool RenderWidgetFullscreenPepper::InitContext() { + gpu::gles2::GLES2Implementation* gl = ggl::GetImplementation(context_); + program_ = gl->CreateProgram(); + + GLuint vertex_shader = + CreateShaderFromSource(gl, GL_VERTEX_SHADER, kVertexShader); + if (!vertex_shader) + return false; + gl->AttachShader(program_, vertex_shader); + gl->DeleteShader(vertex_shader); + + GLuint fragment_shader = + CreateShaderFromSource(gl, GL_FRAGMENT_SHADER, kFragmentShader); + if (!fragment_shader) + return false; + gl->AttachShader(program_, fragment_shader); + gl->DeleteShader(fragment_shader); + + gl->BindAttribLocation(program_, 0, "in_tex_coord"); + gl->LinkProgram(program_); + int status; + gl->GetProgramiv(program_, GL_LINK_STATUS, &status); + if (!status) { + int size = 0; + gl->GetProgramiv(program_, GL_INFO_LOG_LENGTH, &size); + scoped_array<char> log(new char[size]); + gl->GetProgramInfoLog(program_, size, NULL, log.get()); + DLOG(ERROR) << "Link failed: " << log.get(); + return false; + } + gl->UseProgram(program_); + int texture_location = gl->GetUniformLocation(program_, "in_texture"); + gl->Uniform1i(texture_location, 0); + + gl->GenBuffers(1, &buffer_); + gl->BindBuffer(GL_ARRAY_BUFFER, buffer_); + gl->BufferData(GL_ARRAY_BUFFER, + sizeof(kTexCoords), + kTexCoords, + GL_STATIC_DRAW); + gl->VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL); + gl->EnableVertexAttribArray(0); + return true; +} + +bool RenderWidgetFullscreenPepper::CheckCompositing() { + bool compositing = webwidget_->isAcceleratedCompositingActive(); + if (compositing != is_accelerated_compositing_active_) { + didActivateAcceleratedCompositing(compositing); + } + return compositing; +} |