| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/renderer/render_widget_fullscreen_pepper.h" | 5 #include "chrome/renderer/render_widget_fullscreen_pepper.h" |
| 6 | 6 |
| 7 #include "chrome/common/render_messages.h" | 7 #include "chrome/common/render_messages.h" |
| 8 #include "chrome/renderer/ggl/ggl.h" |
| 9 #include "chrome/renderer/gpu_channel_host.h" |
| 10 #include "chrome/renderer/pepper_platform_context_3d_impl.h" |
| 8 #include "chrome/renderer/render_thread.h" | 11 #include "chrome/renderer/render_thread.h" |
| 12 #include "gpu/command_buffer/client/gles2_implementation.h" |
| 9 #include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h" | 13 #include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h" |
| 10 #include "third_party/WebKit/WebKit/chromium/public/WebSize.h" | 14 #include "third_party/WebKit/WebKit/chromium/public/WebSize.h" |
| 11 #include "third_party/WebKit/WebKit/chromium/public/WebWidget.h" | 15 #include "third_party/WebKit/WebKit/chromium/public/WebWidget.h" |
| 12 #include "webkit/plugins/ppapi/fullscreen_container.h" | 16 #include "webkit/plugins/ppapi/plugin_delegate.h" |
| 13 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" | 17 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" |
| 14 | 18 |
| 15 using WebKit::WebCanvas; | 19 using WebKit::WebCanvas; |
| 16 using WebKit::WebCompositionUnderline; | 20 using WebKit::WebCompositionUnderline; |
| 17 using WebKit::WebCursorInfo; | 21 using WebKit::WebCursorInfo; |
| 18 using WebKit::WebInputEvent; | 22 using WebKit::WebInputEvent; |
| 19 using WebKit::WebRect; | 23 using WebKit::WebRect; |
| 20 using WebKit::WebSize; | 24 using WebKit::WebSize; |
| 21 using WebKit::WebString; | 25 using WebKit::WebString; |
| 22 using WebKit::WebTextDirection; | 26 using WebKit::WebTextDirection; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 41 delete this; | 45 delete this; |
| 42 } | 46 } |
| 43 | 47 |
| 44 virtual WebSize size() { | 48 virtual WebSize size() { |
| 45 return size_; | 49 return size_; |
| 46 } | 50 } |
| 47 | 51 |
| 48 virtual void resize(const WebSize& size) { | 52 virtual void resize(const WebSize& size) { |
| 49 size_ = size; | 53 size_ = size; |
| 50 WebRect plugin_rect(0, 0, size_.width, size_.height); | 54 WebRect plugin_rect(0, 0, size_.width, size_.height); |
| 51 // TODO(piman): transparently scale the plugin instead of resizing it. | |
| 52 plugin_->ViewChanged(plugin_rect, plugin_rect); | 55 plugin_->ViewChanged(plugin_rect, plugin_rect); |
| 53 widget_->GenerateFullRepaint(); | 56 widget_->Invalidate(); |
| 54 } | 57 } |
| 55 | 58 |
| 56 virtual void layout() { | 59 virtual void layout() { |
| 57 } | 60 } |
| 58 | 61 |
| 59 virtual void paint(WebCanvas* canvas, const WebRect& rect) { | 62 virtual void paint(WebCanvas* canvas, const WebRect& rect) { |
| 60 if (!plugin_) | 63 if (!plugin_) |
| 61 return; | 64 return; |
| 62 WebRect plugin_rect(0, 0, size_.width, size_.height); | 65 WebRect plugin_rect(0, 0, size_.width, size_.height); |
| 63 plugin_->Paint(canvas, plugin_rect, rect); | 66 plugin_->Paint(canvas, plugin_rect, rect); |
| 64 } | 67 } |
| 65 | 68 |
| 66 virtual void composite(bool finish) { | 69 virtual void composite(bool finish) { |
| 67 NOTIMPLEMENTED(); | 70 ggl::Context* context = widget_->context(); |
| 71 DCHECK(context); |
| 72 gpu::gles2::GLES2Implementation* gl = ggl::GetImplementation(context); |
| 73 unsigned int texture = plugin_->GetBackingTextureId(); |
| 74 gl->BindTexture(GL_TEXTURE_2D, texture); |
| 75 gl->DrawArrays(GL_TRIANGLES, 0, 3); |
| 76 ggl::SwapBuffers(context); |
| 68 } | 77 } |
| 69 | 78 |
| 70 virtual void themeChanged() { | 79 virtual void themeChanged() { |
| 71 NOTIMPLEMENTED(); | 80 NOTIMPLEMENTED(); |
| 72 } | 81 } |
| 73 | 82 |
| 74 virtual bool handleInputEvent(const WebInputEvent& event) { | 83 virtual bool handleInputEvent(const WebInputEvent& event) { |
| 75 if (!plugin_) | 84 if (!plugin_) |
| 76 return false; | 85 return false; |
| 77 return plugin_->HandleInputEvent(event, &cursor_); | 86 return plugin_->HandleInputEvent(event, &cursor_); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 virtual WebRect caretOrSelectionBounds() { | 121 virtual WebRect caretOrSelectionBounds() { |
| 113 NOTIMPLEMENTED(); | 122 NOTIMPLEMENTED(); |
| 114 return WebRect(); | 123 return WebRect(); |
| 115 } | 124 } |
| 116 | 125 |
| 117 virtual void setTextDirection(WebTextDirection) { | 126 virtual void setTextDirection(WebTextDirection) { |
| 118 NOTIMPLEMENTED(); | 127 NOTIMPLEMENTED(); |
| 119 } | 128 } |
| 120 | 129 |
| 121 virtual bool isAcceleratedCompositingActive() const { | 130 virtual bool isAcceleratedCompositingActive() const { |
| 122 // TODO(piman): see if supporting accelerated compositing makes sense. | 131 return widget_->context() && plugin_ && |
| 123 return false; | 132 (plugin_->GetBackingTextureId() != 0); |
| 124 } | 133 } |
| 125 | 134 |
| 126 private: | 135 private: |
| 127 webkit::ppapi::PluginInstance* plugin_; | 136 webkit::ppapi::PluginInstance* plugin_; |
| 128 RenderWidgetFullscreenPepper* widget_; | 137 RenderWidgetFullscreenPepper* widget_; |
| 129 WebSize size_; | 138 WebSize size_; |
| 130 WebCursorInfo cursor_; | 139 WebCursorInfo cursor_; |
| 131 | 140 |
| 132 DISALLOW_COPY_AND_ASSIGN(PepperWidget); | 141 DISALLOW_COPY_AND_ASSIGN(PepperWidget); |
| 133 }; | 142 }; |
| 134 | 143 |
| 135 | |
| 136 // A FullscreenContainer that forwards the API calls to the | |
| 137 // RenderWidgetFullscreenPepper. | |
| 138 class WidgetFullscreenContainer | |
| 139 : public webkit::ppapi::FullscreenContainer { | |
| 140 public: | |
| 141 explicit WidgetFullscreenContainer(RenderWidgetFullscreenPepper* widget) | |
| 142 : widget_(widget) { | |
| 143 } | |
| 144 virtual ~WidgetFullscreenContainer() { } | |
| 145 | |
| 146 virtual void Invalidate() { | |
| 147 widget_->GenerateFullRepaint(); | |
| 148 } | |
| 149 | |
| 150 virtual void InvalidateRect(const WebKit::WebRect& rect) { | |
| 151 widget_->didInvalidateRect(rect); | |
| 152 } | |
| 153 | |
| 154 virtual void ScrollRect(int dx, int dy, const WebKit::WebRect& rect) { | |
| 155 widget_->didScrollRect(dx, dy, rect); | |
| 156 } | |
| 157 | |
| 158 virtual void Destroy() { | |
| 159 widget_->SendClose(); | |
| 160 } | |
| 161 | |
| 162 private: | |
| 163 RenderWidgetFullscreenPepper* widget_; | |
| 164 | |
| 165 DISALLOW_COPY_AND_ASSIGN(WidgetFullscreenContainer); | |
| 166 }; | |
| 167 | |
| 168 } // anonymous namespace | 144 } // anonymous namespace |
| 169 | 145 |
| 170 // static | 146 // static |
| 171 RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create( | 147 RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create( |
| 172 int32 opener_id, RenderThreadBase* render_thread, | 148 int32 opener_id, RenderThreadBase* render_thread, |
| 173 webkit::ppapi::PluginInstance* plugin) { | 149 webkit::ppapi::PluginInstance* plugin) { |
| 174 DCHECK_NE(MSG_ROUTING_NONE, opener_id); | 150 DCHECK_NE(MSG_ROUTING_NONE, opener_id); |
| 175 scoped_refptr<RenderWidgetFullscreenPepper> widget( | 151 scoped_refptr<RenderWidgetFullscreenPepper> widget( |
| 176 new RenderWidgetFullscreenPepper(render_thread, plugin)); | 152 new RenderWidgetFullscreenPepper(render_thread, plugin)); |
| 177 widget->Init(opener_id); | 153 widget->Init(opener_id); |
| 178 return widget.release(); | 154 return widget.release(); |
| 179 } | 155 } |
| 180 | 156 |
| 181 RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper( | 157 RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper( |
| 182 RenderThreadBase* render_thread, | 158 RenderThreadBase* render_thread, |
| 183 webkit::ppapi::PluginInstance* plugin) | 159 webkit::ppapi::PluginInstance* plugin) |
| 184 : RenderWidgetFullscreen(render_thread, WebKit::WebPopupTypeSelect), | 160 : RenderWidgetFullscreen(render_thread, WebKit::WebPopupTypeSelect), |
| 185 plugin_(plugin), | 161 plugin_(plugin), |
| 186 ALLOW_THIS_IN_INITIALIZER_LIST( | 162 #if defined(OS_MACOSX) |
| 187 container_(new WidgetFullscreenContainer(this))) { | 163 plugin_handle_(NULL), |
| 164 #endif |
| 165 context_(NULL), |
| 166 buffer_(0), |
| 167 program_(0) { |
| 188 } | 168 } |
| 189 | 169 |
| 190 RenderWidgetFullscreenPepper::~RenderWidgetFullscreenPepper() { | 170 RenderWidgetFullscreenPepper::~RenderWidgetFullscreenPepper() { |
| 171 DestroyContext(); |
| 191 } | 172 } |
| 192 | 173 |
| 193 WebWidget* RenderWidgetFullscreenPepper::CreateWebWidget() { | 174 void RenderWidgetFullscreenPepper::Invalidate() { |
| 194 return new PepperWidget(plugin_, this); | 175 InvalidateRect(gfx::Rect(size_.width(), size_.height())); |
| 195 } | 176 } |
| 196 | 177 |
| 197 void RenderWidgetFullscreenPepper::Close() { | 178 void RenderWidgetFullscreenPepper::InvalidateRect(const WebKit::WebRect& rect) { |
| 198 // If the fullscreen window is closed (e.g. user pressed escape), reset to | 179 if (CheckCompositing()) { |
| 199 // normal mode. | 180 scheduleComposite(); |
| 200 if (plugin_) | 181 } else { |
| 201 plugin_->SetFullscreen(false); | 182 didInvalidateRect(rect); |
| 183 } |
| 184 } |
| 185 |
| 186 void RenderWidgetFullscreenPepper::ScrollRect( |
| 187 int dx, int dy, const WebKit::WebRect& rect) { |
| 188 if (CheckCompositing()) { |
| 189 scheduleComposite(); |
| 190 } else { |
| 191 didScrollRect(dx, dy, rect); |
| 192 } |
| 193 } |
| 194 |
| 195 void RenderWidgetFullscreenPepper::Destroy() { |
| 196 // This function is called by the plugin instance as it's going away, so reset |
| 197 // plugin_ to NULL to avoid calling into a dangling pointer e.g. on Close(). |
| 198 plugin_ = NULL; |
| 199 Send(new ViewHostMsg_Close(routing_id_)); |
| 200 } |
| 201 |
| 202 webkit::ppapi::PluginDelegate::PlatformContext3D* |
| 203 RenderWidgetFullscreenPepper::CreateContext3D() { |
| 204 if (!context_) { |
| 205 CreateContext(); |
| 206 } |
| 207 if (!context_) |
| 208 return NULL; |
| 209 return new PlatformContext3DImpl(context_); |
| 202 } | 210 } |
| 203 | 211 |
| 204 void RenderWidgetFullscreenPepper::DidInitiatePaint() { | 212 void RenderWidgetFullscreenPepper::DidInitiatePaint() { |
| 205 if (plugin_) | 213 if (plugin_) |
| 206 plugin_->ViewInitiatedPaint(); | 214 plugin_->ViewInitiatedPaint(); |
| 207 } | 215 } |
| 208 | 216 |
| 209 void RenderWidgetFullscreenPepper::DidFlushPaint() { | 217 void RenderWidgetFullscreenPepper::DidFlushPaint() { |
| 210 if (plugin_) | 218 if (plugin_) |
| 211 plugin_->ViewFlushedPaint(); | 219 plugin_->ViewFlushedPaint(); |
| 212 } | 220 } |
| 213 | 221 |
| 214 void RenderWidgetFullscreenPepper::SendClose() { | 222 void RenderWidgetFullscreenPepper::Close() { |
| 215 // This function is called by the plugin instance as it's going away, so reset | 223 // If the fullscreen window is closed (e.g. user pressed escape), reset to |
| 216 // plugin_ to NULL to avoid calling into a dangling pointer e.g. on Close(). | 224 // normal mode. |
| 217 plugin_ = NULL; | 225 if (plugin_) |
| 218 Send(new ViewHostMsg_Close(routing_id_)); | 226 plugin_->SetFullscreen(false); |
| 219 } | |
| 220 | |
| 221 void RenderWidgetFullscreenPepper::GenerateFullRepaint() { | |
| 222 didInvalidateRect(gfx::Rect(size_.width(), size_.height())); | |
| 223 } | 227 } |
| 224 | 228 |
| 225 webkit::ppapi::PluginInstance* | 229 webkit::ppapi::PluginInstance* |
| 226 RenderWidgetFullscreenPepper::GetBitmapForOptimizedPluginPaint( | 230 RenderWidgetFullscreenPepper::GetBitmapForOptimizedPluginPaint( |
| 227 const gfx::Rect& paint_bounds, | 231 const gfx::Rect& paint_bounds, |
| 228 TransportDIB** dib, | 232 TransportDIB** dib, |
| 229 gfx::Rect* location, | 233 gfx::Rect* location, |
| 230 gfx::Rect* clip) { | 234 gfx::Rect* clip) { |
| 231 if (plugin_ && | 235 if (plugin_ && |
| 232 plugin_->GetBitmapForOptimizedPluginPaint(paint_bounds, dib, | 236 plugin_->GetBitmapForOptimizedPluginPaint(paint_bounds, dib, |
| 233 location, clip)) | 237 location, clip)) |
| 234 return plugin_; | 238 return plugin_; |
| 235 return NULL; | 239 return NULL; |
| 236 } | 240 } |
| 241 |
| 242 void RenderWidgetFullscreenPepper::OnResize(const gfx::Size& size, |
| 243 const gfx::Rect& resizer_rect) { |
| 244 if (context_) { |
| 245 #if defined(OS_MACOSX) |
| 246 ggl::ResizeOnscreenContext(context_, size); |
| 247 #else |
| 248 gpu::gles2::GLES2Implementation* gl = ggl::GetImplementation(context_); |
| 249 gl->ResizeCHROMIUM(size.width(), size.height()); |
| 250 #endif |
| 251 gl->Viewport(0, 0, size.width(), size.height()); |
| 252 } |
| 253 RenderWidget::OnResize(size, resizer_rect); |
| 254 } |
| 255 |
| 256 WebWidget* RenderWidgetFullscreenPepper::CreateWebWidget() { |
| 257 return new PepperWidget(plugin_, this); |
| 258 } |
| 259 |
| 260 void RenderWidgetFullscreenPepper::CreateContext() { |
| 261 DCHECK(!context_); |
| 262 RenderThread* render_thread = RenderThread::current(); |
| 263 DCHECK(render_thread); |
| 264 GpuChannelHost* host = render_thread->EstablishGpuChannelSync(); |
| 265 if (!host) |
| 266 return; |
| 267 gfx::NativeViewId view_id; |
| 268 #if !defined(OS_MACOSX) |
| 269 view_id = host_window(); |
| 270 #else |
| 271 Send(new ViewHostMsg_AllocateFakePluginWindowHandle( |
| 272 routing_id(), true, true, &plugin_handle_)); |
| 273 if (!plugin_handle_) |
| 274 return; |
| 275 view_id = static_cast<gfx::NativeViewId>(plugin_handle_); |
| 276 #endif |
| 277 const int32 attribs[] = { |
| 278 ggl::GGL_ALPHA_SIZE, 8, |
| 279 ggl::GGL_DEPTH_SIZE, 0, |
| 280 ggl::GGL_STENCIL_SIZE, 0, |
| 281 ggl::GGL_SAMPLES, 0, |
| 282 ggl::GGL_SAMPLE_BUFFERS, 0, |
| 283 ggl::GGL_NONE, |
| 284 }; |
| 285 context_ = ggl::CreateViewContext( |
| 286 host, |
| 287 view_id, |
| 288 routing_id(), |
| 289 "GL_OES_packed_depth_stencil GL_OES_depth24", |
| 290 attribs); |
| 291 if (!context_ || !InitContext()) { |
| 292 DestroyContext(); |
| 293 return; |
| 294 } |
| 295 ggl::SetSwapBuffersCallback( |
| 296 context_, |
| 297 NewCallback(this, &RenderWidgetFullscreenPepper::DidFlushPaint)); |
| 298 } |
| 299 |
| 300 void RenderWidgetFullscreenPepper::DestroyContext() { |
| 301 if (context_) { |
| 302 gpu::gles2::GLES2Implementation* gl = ggl::GetImplementation(context_); |
| 303 if (program_) { |
| 304 gl->DeleteProgram(program_); |
| 305 program_ = 0; |
| 306 } |
| 307 if (buffer_) { |
| 308 gl->DeleteBuffers(1, &buffer_); |
| 309 buffer_ = 0; |
| 310 } |
| 311 ggl::DestroyContext(context_); |
| 312 context_ = NULL; |
| 313 } |
| 314 #if defined(OS_MACOSX) |
| 315 if (plugin_handle_) { |
| 316 Send(new ViewHostMsg_DestroyFakePluginWindowHandle(routing_id(), |
| 317 plugin_handle_)); |
| 318 plugin_handle_ = NULL; |
| 319 } |
| 320 #endif |
| 321 } |
| 322 |
| 323 namespace { |
| 324 |
| 325 const char kVertexShader[] = |
| 326 "attribute vec2 in_tex_coord;\n" |
| 327 "varying vec2 tex_coord;\n" |
| 328 "void main() {\n" |
| 329 " gl_Position = vec4(in_tex_coord.x * 2. - 1.,\n" |
| 330 " in_tex_coord.y * 2. - 1.,\n" |
| 331 " 0.,\n" |
| 332 " 1.);\n" |
| 333 " tex_coord = vec2(in_tex_coord.x, 1. - in_tex_coord.y);\n" |
| 334 "}\n"; |
| 335 |
| 336 const char kFragmentShader[] = |
| 337 "precision mediump float;\n" |
| 338 "varying vec2 tex_coord;\n" |
| 339 "uniform sampler2D in_texture;\n" |
| 340 "void main() {\n" |
| 341 " gl_FragColor = texture2D(in_texture, tex_coord);\n" |
| 342 "}\n"; |
| 343 |
| 344 GLuint CreateShaderFromSource(gpu::gles2::GLES2Implementation* gl, |
| 345 GLenum type, |
| 346 const char* source) { |
| 347 GLuint shader = gl->CreateShader(type); |
| 348 gl->ShaderSource(shader, 1, &source, NULL); |
| 349 gl->CompileShader(shader); |
| 350 int status; |
| 351 gl->GetShaderiv(shader, GL_COMPILE_STATUS, &status); |
| 352 if (!status) { |
| 353 int size = 0; |
| 354 gl->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &size); |
| 355 scoped_array<char> log(new char[size]); |
| 356 gl->GetShaderInfoLog(shader, size, NULL, log.get()); |
| 357 DLOG(ERROR) << "Compilation failed: " << log.get(); |
| 358 gl->DeleteShader(shader); |
| 359 shader = 0; |
| 360 } |
| 361 return shader; |
| 362 } |
| 363 |
| 364 const float kTexCoords[] = { |
| 365 0.f, 0.f, |
| 366 0.f, 2.f, |
| 367 2.f, 0.f, |
| 368 }; |
| 369 |
| 370 } // anonymous namespace |
| 371 |
| 372 bool RenderWidgetFullscreenPepper::InitContext() { |
| 373 gpu::gles2::GLES2Implementation* gl = ggl::GetImplementation(context_); |
| 374 program_ = gl->CreateProgram(); |
| 375 |
| 376 GLuint vertex_shader = |
| 377 CreateShaderFromSource(gl, GL_VERTEX_SHADER, kVertexShader); |
| 378 if (!vertex_shader) |
| 379 return false; |
| 380 gl->AttachShader(program_, vertex_shader); |
| 381 gl->DeleteShader(vertex_shader); |
| 382 |
| 383 GLuint fragment_shader = |
| 384 CreateShaderFromSource(gl, GL_FRAGMENT_SHADER, kFragmentShader); |
| 385 if (!fragment_shader) |
| 386 return false; |
| 387 gl->AttachShader(program_, fragment_shader); |
| 388 gl->DeleteShader(fragment_shader); |
| 389 |
| 390 gl->BindAttribLocation(program_, 0, "in_tex_coord"); |
| 391 gl->LinkProgram(program_); |
| 392 int status; |
| 393 gl->GetProgramiv(program_, GL_LINK_STATUS, &status); |
| 394 if (!status) { |
| 395 int size = 0; |
| 396 gl->GetProgramiv(program_, GL_INFO_LOG_LENGTH, &size); |
| 397 scoped_array<char> log(new char[size]); |
| 398 gl->GetProgramInfoLog(program_, size, NULL, log.get()); |
| 399 DLOG(ERROR) << "Link failed: " << log.get(); |
| 400 return false; |
| 401 } |
| 402 gl->UseProgram(program_); |
| 403 int texture_location = gl->GetUniformLocation(program_, "in_texture"); |
| 404 gl->Uniform1i(texture_location, 0); |
| 405 |
| 406 gl->GenBuffers(1, &buffer_); |
| 407 gl->BindBuffer(GL_ARRAY_BUFFER, buffer_); |
| 408 gl->BufferData(GL_ARRAY_BUFFER, |
| 409 sizeof(kTexCoords), |
| 410 kTexCoords, |
| 411 GL_STATIC_DRAW); |
| 412 gl->VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL); |
| 413 gl->EnableVertexAttribArray(0); |
| 414 return true; |
| 415 } |
| 416 |
| 417 bool RenderWidgetFullscreenPepper::CheckCompositing() { |
| 418 bool compositing = webwidget_->isAcceleratedCompositingActive(); |
| 419 if (compositing != is_accelerated_compositing_active_) { |
| 420 didActivateAcceleratedCompositing(compositing); |
| 421 } |
| 422 return compositing; |
| 423 } |
| OLD | NEW |