| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #if defined(ENABLE_GPU) | 5 #if defined(ENABLE_GPU) |
| 6 | 6 |
| 7 #include "content/common/gpu/image_transport_surface.h" | 7 #include "content/common/gpu/image_transport_surface.h" |
| 8 | 8 |
| 9 #include "base/mac/scoped_cftyperef.h" | 9 #include "base/mac/scoped_cftyperef.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 gfx::Size size_; | 64 gfx::Size size_; |
| 65 | 65 |
| 66 // Whether or not we've successfully made the surface current once. | 66 // Whether or not we've successfully made the surface current once. |
| 67 bool made_current_; | 67 bool made_current_; |
| 68 | 68 |
| 69 scoped_ptr<ImageTransportHelper> helper_; | 69 scoped_ptr<ImageTransportHelper> helper_; |
| 70 | 70 |
| 71 DISALLOW_COPY_AND_ASSIGN(IOSurfaceImageTransportSurface); | 71 DISALLOW_COPY_AND_ASSIGN(IOSurfaceImageTransportSurface); |
| 72 }; | 72 }; |
| 73 | 73 |
| 74 // We are backed by an offscreen surface for the purposes of creating | |
| 75 // a context, but use FBOs to render to texture backed IOSurface | |
| 76 class TransportDIBImageTransportSurface : public gfx::NoOpGLSurfaceCGL, | |
| 77 public ImageTransportSurface { | |
| 78 public: | |
| 79 TransportDIBImageTransportSurface(GpuChannelManager* manager, | |
| 80 GpuCommandBufferStub* stub, | |
| 81 gfx::PluginWindowHandle handle); | |
| 82 | |
| 83 // GLSurface implementation | |
| 84 virtual bool Initialize() OVERRIDE; | |
| 85 virtual void Destroy() OVERRIDE; | |
| 86 virtual bool IsOffscreen() OVERRIDE; | |
| 87 virtual bool SwapBuffers() OVERRIDE; | |
| 88 virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE; | |
| 89 virtual std::string GetExtensions() OVERRIDE; | |
| 90 virtual gfx::Size GetSize() OVERRIDE; | |
| 91 virtual bool OnMakeCurrent(gfx::GLContext* context) OVERRIDE; | |
| 92 virtual unsigned int GetBackingFrameBufferObject() OVERRIDE; | |
| 93 | |
| 94 protected: | |
| 95 // ImageTransportSurface implementation | |
| 96 virtual void OnBuffersSwappedACK() OVERRIDE; | |
| 97 virtual void OnPostSubBufferACK() OVERRIDE; | |
| 98 virtual void OnNewSurfaceACK(uint64 surface_handle, | |
| 99 TransportDIB::Handle shm_handle) OVERRIDE; | |
| 100 virtual void OnResizeViewACK() OVERRIDE; | |
| 101 virtual void OnResize(gfx::Size size) OVERRIDE; | |
| 102 | |
| 103 private: | |
| 104 virtual ~TransportDIBImageTransportSurface() OVERRIDE; | |
| 105 | |
| 106 uint32 fbo_id_; | |
| 107 GLuint render_buffer_id_; | |
| 108 | |
| 109 scoped_ptr<TransportDIB> shared_mem_; | |
| 110 | |
| 111 gfx::Size size_; | |
| 112 | |
| 113 static uint32 next_handle_; | |
| 114 | |
| 115 // Whether or not we've successfully made the surface current once. | |
| 116 bool made_current_; | |
| 117 | |
| 118 scoped_ptr<ImageTransportHelper> helper_; | |
| 119 | |
| 120 DISALLOW_COPY_AND_ASSIGN(TransportDIBImageTransportSurface); | |
| 121 }; | |
| 122 | |
| 123 uint32 TransportDIBImageTransportSurface::next_handle_ = 1; | |
| 124 | |
| 125 void AddBooleanValue(CFMutableDictionaryRef dictionary, | 74 void AddBooleanValue(CFMutableDictionaryRef dictionary, |
| 126 const CFStringRef key, | 75 const CFStringRef key, |
| 127 bool value) { | 76 bool value) { |
| 128 CFDictionaryAddValue(dictionary, key, | 77 CFDictionaryAddValue(dictionary, key, |
| 129 (value ? kCFBooleanTrue : kCFBooleanFalse)); | 78 (value ? kCFBooleanTrue : kCFBooleanFalse)); |
| 130 } | 79 } |
| 131 | 80 |
| 132 void AddIntegerValue(CFMutableDictionaryRef dictionary, | 81 void AddIntegerValue(CFMutableDictionaryRef dictionary, |
| 133 const CFStringRef key, | 82 const CFStringRef key, |
| 134 int32 value) { | 83 int32 value) { |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 helper_->SetScheduled(true); | 202 helper_->SetScheduled(true); |
| 254 } | 203 } |
| 255 | 204 |
| 256 void IOSurfaceImageTransportSurface::OnPostSubBufferACK() { | 205 void IOSurfaceImageTransportSurface::OnPostSubBufferACK() { |
| 257 helper_->SetScheduled(true); | 206 helper_->SetScheduled(true); |
| 258 } | 207 } |
| 259 | 208 |
| 260 void IOSurfaceImageTransportSurface::OnNewSurfaceACK( | 209 void IOSurfaceImageTransportSurface::OnNewSurfaceACK( |
| 261 uint64 surface_handle, | 210 uint64 surface_handle, |
| 262 TransportDIB::Handle /* shm_handle */) { | 211 TransportDIB::Handle /* shm_handle */) { |
| 263 DCHECK_EQ(io_surface_handle_, surface_handle); | 212 NOTREACHED(); |
| 264 helper_->SetScheduled(true); | |
| 265 } | 213 } |
| 266 | 214 |
| 267 void IOSurfaceImageTransportSurface::OnResizeViewACK() { | 215 void IOSurfaceImageTransportSurface::OnResizeViewACK() { |
| 268 NOTREACHED(); | 216 NOTREACHED(); |
| 269 } | 217 } |
| 270 | 218 |
| 271 void IOSurfaceImageTransportSurface::OnResize(gfx::Size size) { | 219 void IOSurfaceImageTransportSurface::OnResize(gfx::Size size) { |
| 272 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); | 220 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); |
| 273 | 221 |
| 274 // Caching |context_| from OnMakeCurrent. It should still be current. | 222 // Caching |context_| from OnMakeCurrent. It should still be current. |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 GL_BGRA, | 287 GL_BGRA, |
| 340 GL_UNSIGNED_INT_8_8_8_8_REV, | 288 GL_UNSIGNED_INT_8_8_8_8_REV, |
| 341 io_surface_.get(), | 289 io_surface_.get(), |
| 342 plane); | 290 plane); |
| 343 | 291 |
| 344 io_surface_handle_ = io_surface_support->IOSurfaceGetID(io_surface_); | 292 io_surface_handle_ = io_surface_support->IOSurfaceGetID(io_surface_); |
| 345 glFlush(); | 293 glFlush(); |
| 346 | 294 |
| 347 glBindTexture(target, previous_texture_id); | 295 glBindTexture(target, previous_texture_id); |
| 348 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, previous_fbo_id); | 296 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, previous_fbo_id); |
| 349 | |
| 350 GpuHostMsg_AcceleratedSurfaceNew_Params params; | |
| 351 params.width = size_.width(); | |
| 352 params.height = size_.height(); | |
| 353 params.surface_handle = io_surface_handle_; | |
| 354 params.create_transport_dib = false; | |
| 355 helper_->SendAcceleratedSurfaceNew(params); | |
| 356 | |
| 357 helper_->SetScheduled(false); | |
| 358 } | |
| 359 | |
| 360 TransportDIBImageTransportSurface::TransportDIBImageTransportSurface( | |
| 361 GpuChannelManager* manager, | |
| 362 GpuCommandBufferStub* stub, | |
| 363 gfx::PluginWindowHandle handle) | |
| 364 : gfx::NoOpGLSurfaceCGL(gfx::Size(1, 1)), | |
| 365 fbo_id_(0), | |
| 366 render_buffer_id_(0), | |
| 367 made_current_(false) { | |
| 368 helper_.reset(new ImageTransportHelper(this, manager, stub, handle)); | |
| 369 | |
| 370 } | |
| 371 | |
| 372 TransportDIBImageTransportSurface::~TransportDIBImageTransportSurface() { | |
| 373 Destroy(); | |
| 374 } | |
| 375 | |
| 376 bool TransportDIBImageTransportSurface::Initialize() { | |
| 377 if (!helper_->Initialize()) | |
| 378 return false; | |
| 379 return NoOpGLSurfaceCGL::Initialize(); | |
| 380 } | |
| 381 | |
| 382 void TransportDIBImageTransportSurface::Destroy() { | |
| 383 if (fbo_id_) { | |
| 384 glDeleteFramebuffersEXT(1, &fbo_id_); | |
| 385 fbo_id_ = 0; | |
| 386 } | |
| 387 | |
| 388 if (render_buffer_id_) { | |
| 389 glDeleteRenderbuffersEXT(1, &render_buffer_id_); | |
| 390 render_buffer_id_ = 0; | |
| 391 } | |
| 392 | |
| 393 helper_->Destroy(); | |
| 394 NoOpGLSurfaceCGL::Destroy(); | |
| 395 } | |
| 396 | |
| 397 bool TransportDIBImageTransportSurface::IsOffscreen() { | |
| 398 return false; | |
| 399 } | |
| 400 | |
| 401 bool TransportDIBImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) { | |
| 402 if (made_current_) | |
| 403 return true; | |
| 404 | |
| 405 glGenFramebuffersEXT(1, &fbo_id_); | |
| 406 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_); | |
| 407 OnResize(gfx::Size(1, 1)); | |
| 408 | |
| 409 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); | |
| 410 if (status != GL_FRAMEBUFFER_COMPLETE) { | |
| 411 DLOG(ERROR) << "Framebuffer incomplete."; | |
| 412 return false; | |
| 413 } | |
| 414 | |
| 415 made_current_ = true; | |
| 416 return true; | |
| 417 } | |
| 418 | |
| 419 unsigned int TransportDIBImageTransportSurface::GetBackingFrameBufferObject() { | |
| 420 return fbo_id_; | |
| 421 } | |
| 422 | |
| 423 bool TransportDIBImageTransportSurface::SwapBuffers() { | |
| 424 DCHECK_NE(shared_mem_.get(), static_cast<void*>(NULL)); | |
| 425 | |
| 426 GLint previous_fbo_id = 0; | |
| 427 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &previous_fbo_id); | |
| 428 | |
| 429 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_); | |
| 430 | |
| 431 GLint current_alignment = 0; | |
| 432 glGetIntegerv(GL_PACK_ALIGNMENT, ¤t_alignment); | |
| 433 glPixelStorei(GL_PACK_ALIGNMENT, 4); | |
| 434 glReadPixels(0, 0, | |
| 435 size_.width(), size_.height(), | |
| 436 GL_BGRA, // This pixel format should have no conversion. | |
| 437 GL_UNSIGNED_INT_8_8_8_8_REV, | |
| 438 shared_mem_->memory()); | |
| 439 glPixelStorei(GL_PACK_ALIGNMENT, current_alignment); | |
| 440 | |
| 441 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, previous_fbo_id); | |
| 442 | |
| 443 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params; | |
| 444 params.surface_handle = next_handle_; | |
| 445 helper_->SendAcceleratedSurfaceBuffersSwapped(params); | |
| 446 | |
| 447 helper_->SetScheduled(false); | |
| 448 return true; | |
| 449 } | |
| 450 | |
| 451 bool TransportDIBImageTransportSurface::PostSubBuffer( | |
| 452 int x, int y, int width, int height) { | |
| 453 DCHECK_NE(shared_mem_.get(), static_cast<void*>(NULL)); | |
| 454 | |
| 455 GLint previous_fbo_id = 0; | |
| 456 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &previous_fbo_id); | |
| 457 | |
| 458 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_); | |
| 459 | |
| 460 GLint current_alignment = 0, current_pack_row_length = 0; | |
| 461 glGetIntegerv(GL_PACK_ALIGNMENT, ¤t_alignment); | |
| 462 glGetIntegerv(GL_PACK_ROW_LENGTH, ¤t_pack_row_length); | |
| 463 | |
| 464 glPixelStorei(GL_PACK_ALIGNMENT, 4); | |
| 465 glPixelStorei(GL_PACK_ROW_LENGTH, size_.width()); | |
| 466 | |
| 467 unsigned char* buffer = | |
| 468 static_cast<unsigned char*>(shared_mem_->memory()); | |
| 469 glReadPixels(x, y, | |
| 470 width, height, | |
| 471 GL_BGRA, // This pixel format should have no conversion. | |
| 472 GL_UNSIGNED_INT_8_8_8_8_REV, | |
| 473 &buffer[(x + y * size_.width()) * 4]); | |
| 474 | |
| 475 glPixelStorei(GL_PACK_ALIGNMENT, current_alignment); | |
| 476 glPixelStorei(GL_PACK_ROW_LENGTH, current_pack_row_length); | |
| 477 | |
| 478 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, previous_fbo_id); | |
| 479 | |
| 480 GpuHostMsg_AcceleratedSurfacePostSubBuffer_Params params; | |
| 481 params.surface_handle = next_handle_; | |
| 482 params.x = x; | |
| 483 params.y = y; | |
| 484 params.width = width; | |
| 485 params.height = height; | |
| 486 helper_->SendAcceleratedSurfacePostSubBuffer(params); | |
| 487 | |
| 488 helper_->SetScheduled(false); | |
| 489 return true; | |
| 490 } | |
| 491 | |
| 492 std::string TransportDIBImageTransportSurface::GetExtensions() { | |
| 493 std::string extensions = gfx::GLSurface::GetExtensions(); | |
| 494 extensions += extensions.empty() ? "" : " "; | |
| 495 extensions += "GL_CHROMIUM_front_buffer_cached "; | |
| 496 extensions += "GL_CHROMIUM_post_sub_buffer"; | |
| 497 return extensions; | |
| 498 } | |
| 499 | |
| 500 gfx::Size TransportDIBImageTransportSurface::GetSize() { | |
| 501 return size_; | |
| 502 } | |
| 503 | |
| 504 void TransportDIBImageTransportSurface::OnBuffersSwappedACK() { | |
| 505 helper_->SetScheduled(true); | |
| 506 } | |
| 507 | |
| 508 void TransportDIBImageTransportSurface::OnPostSubBufferACK() { | |
| 509 helper_->SetScheduled(true); | |
| 510 } | |
| 511 | |
| 512 void TransportDIBImageTransportSurface::OnNewSurfaceACK( | |
| 513 uint64 surface_handle, | |
| 514 TransportDIB::Handle shm_handle) { | |
| 515 helper_->SetScheduled(true); | |
| 516 | |
| 517 shared_mem_.reset(TransportDIB::Map(shm_handle)); | |
| 518 DCHECK_NE(shared_mem_.get(), static_cast<void*>(NULL)); | |
| 519 } | |
| 520 | |
| 521 void TransportDIBImageTransportSurface::OnResizeViewACK() { | |
| 522 NOTREACHED(); | |
| 523 } | |
| 524 | |
| 525 void TransportDIBImageTransportSurface::OnResize(gfx::Size size) { | |
| 526 size_ = size; | |
| 527 | |
| 528 if (!render_buffer_id_) | |
| 529 glGenRenderbuffersEXT(1, &render_buffer_id_); | |
| 530 | |
| 531 GLint previous_fbo_id = 0; | |
| 532 glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &previous_fbo_id); | |
| 533 | |
| 534 GLint previous_renderbuffer_id = 0; | |
| 535 glGetIntegerv(GL_RENDERBUFFER_BINDING_EXT, &previous_renderbuffer_id); | |
| 536 | |
| 537 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_); | |
| 538 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_buffer_id_); | |
| 539 | |
| 540 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, | |
| 541 GL_RGBA, | |
| 542 size_.width(), size_.height()); | |
| 543 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, | |
| 544 GL_COLOR_ATTACHMENT0_EXT, | |
| 545 GL_RENDERBUFFER_EXT, | |
| 546 render_buffer_id_); | |
| 547 | |
| 548 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, previous_renderbuffer_id); | |
| 549 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, previous_fbo_id); | |
| 550 | |
| 551 GpuHostMsg_AcceleratedSurfaceNew_Params params; | |
| 552 params.width = size_.width(); | |
| 553 params.height = size_.height(); | |
| 554 params.surface_handle = next_handle_++; | |
| 555 params.create_transport_dib = true; | |
| 556 helper_->SendAcceleratedSurfaceNew(params); | |
| 557 | |
| 558 helper_->SetScheduled(false); | |
| 559 } | 297 } |
| 560 | 298 |
| 561 } // namespace | 299 } // namespace |
| 562 | 300 |
| 563 // static | 301 // static |
| 564 scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface( | 302 scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface( |
| 565 GpuChannelManager* manager, | 303 GpuChannelManager* manager, |
| 566 GpuCommandBufferStub* stub, | 304 GpuCommandBufferStub* stub, |
| 567 const gfx::GLSurfaceHandle& surface_handle) { | 305 const gfx::GLSurfaceHandle& surface_handle) { |
| 568 scoped_refptr<gfx::GLSurface> surface; | 306 scoped_refptr<gfx::GLSurface> surface; |
| 569 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); | 307 IOSurfaceSupport* io_surface_support = IOSurfaceSupport::Initialize(); |
| 570 | 308 |
| 571 switch (gfx::GetGLImplementation()) { | 309 switch (gfx::GetGLImplementation()) { |
| 572 case gfx::kGLImplementationDesktopGL: | 310 case gfx::kGLImplementationDesktopGL: |
| 573 case gfx::kGLImplementationAppleGL: | 311 case gfx::kGLImplementationAppleGL: |
| 574 if (!io_surface_support) { | 312 if (!io_surface_support) { |
| 575 surface = new TransportDIBImageTransportSurface( | 313 DLOG(WARNING) << "No IOSurface support"; |
| 576 manager, stub, surface_handle.handle); | 314 return NULL; |
| 577 } else { | 315 } else { |
| 578 surface = new IOSurfaceImageTransportSurface( | 316 surface = new IOSurfaceImageTransportSurface( |
| 579 manager, stub, surface_handle.handle); | 317 manager, stub, surface_handle.handle); |
| 580 } | 318 } |
| 581 break; | 319 break; |
| 582 default: | 320 default: |
| 583 NOTREACHED(); | 321 NOTREACHED(); |
| 584 return NULL; | 322 return NULL; |
| 585 } | 323 } |
| 586 if (surface->Initialize()) | 324 if (surface->Initialize()) |
| 587 return surface; | 325 return surface; |
| 588 else | 326 else |
| 589 return NULL; | 327 return NULL; |
| 590 } | 328 } |
| 591 | 329 |
| 592 #endif // defined(USE_GPU) | 330 #endif // defined(USE_GPU) |
| OLD | NEW |