| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "media/gpu/dxva_picture_buffer_win.h" | 5 #include "media/gpu/dxva_picture_buffer_win.h" |
| 6 | 6 |
| 7 #include "media/gpu/dxva_video_decode_accelerator_win.h" | 7 #include "media/gpu/dxva_video_decode_accelerator_win.h" |
| 8 #include "third_party/angle/include/EGL/egl.h" | 8 #include "third_party/angle/include/EGL/egl.h" |
| 9 #include "third_party/angle/include/EGL/eglext.h" | 9 #include "third_party/angle/include/EGL/eglext.h" |
| 10 #include "ui/gl/gl_bindings.h" | 10 #include "ui/gl/gl_bindings.h" |
| 11 #include "ui/gl/gl_context.h" | 11 #include "ui/gl/gl_context.h" |
| 12 #include "ui/gl/gl_fence.h" | 12 #include "ui/gl/gl_fence.h" |
| 13 #include "ui/gl/gl_image.h" |
| 13 #include "ui/gl/gl_surface_egl.h" | 14 #include "ui/gl/gl_surface_egl.h" |
| 14 #include "ui/gl/scoped_binders.h" | 15 #include "ui/gl/scoped_binders.h" |
| 15 | 16 |
| 16 namespace media { | 17 namespace media { |
| 17 | 18 |
| 18 namespace { | 19 namespace { |
| 19 | 20 |
| 20 void LogDXVAError(int line) { | 21 void LogDXVAError(int line) { |
| 21 LOG(ERROR) << "Error in dxva_picture_buffer_win.cc on line " << line; | 22 LOG(ERROR) << "Error in dxva_picture_buffer_win.cc on line " << line; |
| 22 } | 23 } |
| 23 | 24 |
| 25 // These GLImage subclasses are just used to hold references to the underlying |
| 26 // image content so it can be destroyed when the textures are. |
| 27 class DummyGLImage : public gl::GLImage { |
| 28 public: |
| 29 DummyGLImage(const gfx::Size& size) : size_(size) {} |
| 30 |
| 31 // gl::GLImage implementation. |
| 32 gfx::Size GetSize() override { return size_; } |
| 33 unsigned GetInternalFormat() override { return GL_BGRA_EXT; } |
| 34 bool BindTexImage(unsigned target) override { return false; } |
| 35 void ReleaseTexImage(unsigned target) override {} |
| 36 bool CopyTexImage(unsigned target) override { return false; } |
| 37 bool CopyTexSubImage(unsigned target, |
| 38 const gfx::Point& offset, |
| 39 const gfx::Rect& rect) override { |
| 40 return false; |
| 41 } |
| 42 bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget, |
| 43 int z_order, |
| 44 gfx::OverlayTransform transform, |
| 45 const gfx::Rect& bounds_rect, |
| 46 const gfx::RectF& crop_rect) override { |
| 47 return false; |
| 48 } |
| 49 void Flush() override {} |
| 50 void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, |
| 51 uint64_t process_tracing_id, |
| 52 const std::string& dump_name) override {} |
| 53 |
| 54 protected: |
| 55 ~DummyGLImage() override {} |
| 56 |
| 57 private: |
| 58 gfx::Size size_; |
| 59 }; |
| 60 |
| 61 class GLImagePbuffer : public DummyGLImage { |
| 62 public: |
| 63 GLImagePbuffer(const gfx::Size& size, EGLSurface surface) |
| 64 : DummyGLImage(size), surface_(surface) {} |
| 65 |
| 66 private: |
| 67 ~GLImagePbuffer() override { |
| 68 EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); |
| 69 |
| 70 eglReleaseTexImage(egl_display, surface_, EGL_BACK_BUFFER); |
| 71 |
| 72 eglDestroySurface(egl_display, surface_); |
| 73 } |
| 74 |
| 75 EGLSurface surface_; |
| 76 }; |
| 77 |
| 78 class GLImageEGLStream : public DummyGLImage { |
| 79 public: |
| 80 GLImageEGLStream(const gfx::Size& size, EGLStreamKHR stream) |
| 81 : DummyGLImage(size), stream_(stream) {} |
| 82 |
| 83 private: |
| 84 ~GLImageEGLStream() override { |
| 85 EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); |
| 86 eglDestroyStreamKHR(egl_display, stream_); |
| 87 } |
| 88 |
| 89 EGLStreamKHR stream_; |
| 90 }; |
| 91 |
| 24 } // namespace | 92 } // namespace |
| 25 | 93 |
| 26 #define RETURN_ON_FAILURE(result, log, ret) \ | 94 #define RETURN_ON_FAILURE(result, log, ret) \ |
| 27 do { \ | 95 do { \ |
| 28 if (!(result)) { \ | 96 if (!(result)) { \ |
| 29 DLOG(ERROR) << log; \ | 97 DLOG(ERROR) << log; \ |
| 30 LogDXVAError(__LINE__); \ | 98 LogDXVAError(__LINE__); \ |
| 31 return ret; \ | 99 return ret; \ |
| 32 } \ | 100 } \ |
| 33 } while (0) | 101 } while (0) |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 EGL_TEXTURE_FORMAT, | 199 EGL_TEXTURE_FORMAT, |
| 132 use_rgb ? EGL_TEXTURE_RGB : EGL_TEXTURE_RGBA, | 200 use_rgb ? EGL_TEXTURE_RGB : EGL_TEXTURE_RGBA, |
| 133 EGL_TEXTURE_TARGET, | 201 EGL_TEXTURE_TARGET, |
| 134 EGL_TEXTURE_2D, | 202 EGL_TEXTURE_2D, |
| 135 EGL_NONE}; | 203 EGL_NONE}; |
| 136 | 204 |
| 137 decoding_surface_ = eglCreatePbufferFromClientBuffer( | 205 decoding_surface_ = eglCreatePbufferFromClientBuffer( |
| 138 egl_display, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, texture_share_handle_, | 206 egl_display, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, texture_share_handle_, |
| 139 egl_config, attrib_list); | 207 egl_config, attrib_list); |
| 140 RETURN_ON_FAILURE(decoding_surface_, "Failed to create surface", false); | 208 RETURN_ON_FAILURE(decoding_surface_, "Failed to create surface", false); |
| 209 gl_image_ = make_scoped_refptr(new GLImagePbuffer(size(), decoding_surface_)); |
| 141 if (decoder.d3d11_device_ && decoder.use_keyed_mutex_) { | 210 if (decoder.d3d11_device_ && decoder.use_keyed_mutex_) { |
| 142 void* keyed_mutex = nullptr; | 211 void* keyed_mutex = nullptr; |
| 143 EGLBoolean ret = | 212 EGLBoolean ret = |
| 144 eglQuerySurfacePointerANGLE(egl_display, decoding_surface_, | 213 eglQuerySurfacePointerANGLE(egl_display, decoding_surface_, |
| 145 EGL_DXGI_KEYED_MUTEX_ANGLE, &keyed_mutex); | 214 EGL_DXGI_KEYED_MUTEX_ANGLE, &keyed_mutex); |
| 146 RETURN_ON_FAILURE(keyed_mutex && ret == EGL_TRUE, | 215 RETURN_ON_FAILURE(keyed_mutex && ret == EGL_TRUE, |
| 147 "Failed to query ANGLE keyed mutex", false); | 216 "Failed to query ANGLE keyed mutex", false); |
| 148 egl_keyed_mutex_ = base::win::ScopedComPtr<IDXGIKeyedMutex>( | 217 egl_keyed_mutex_ = base::win::ScopedComPtr<IDXGIKeyedMutex>( |
| 149 static_cast<IDXGIKeyedMutex*>(keyed_mutex)); | 218 static_cast<IDXGIKeyedMutex*>(keyed_mutex)); |
| 150 } | 219 } |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 306 } | 375 } |
| 307 | 376 |
| 308 PbufferPictureBuffer::PbufferPictureBuffer(const PictureBuffer& buffer) | 377 PbufferPictureBuffer::PbufferPictureBuffer(const PictureBuffer& buffer) |
| 309 : DXVAPictureBuffer(buffer), | 378 : DXVAPictureBuffer(buffer), |
| 310 decoding_surface_(NULL), | 379 decoding_surface_(NULL), |
| 311 texture_share_handle_(nullptr), | 380 texture_share_handle_(nullptr), |
| 312 keyed_mutex_value_(0), | 381 keyed_mutex_value_(0), |
| 313 use_rgb_(true) {} | 382 use_rgb_(true) {} |
| 314 | 383 |
| 315 PbufferPictureBuffer::~PbufferPictureBuffer() { | 384 PbufferPictureBuffer::~PbufferPictureBuffer() { |
| 316 if (decoding_surface_) { | 385 // decoding_surface_ will be deleted by gl_image_. |
| 317 EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); | |
| 318 | |
| 319 eglReleaseTexImage(egl_display, decoding_surface_, EGL_BACK_BUFFER); | |
| 320 | |
| 321 eglDestroySurface(egl_display, decoding_surface_); | |
| 322 decoding_surface_ = NULL; | |
| 323 } | |
| 324 } | 386 } |
| 325 | 387 |
| 326 bool PbufferPictureBuffer::ReusePictureBuffer() { | 388 bool PbufferPictureBuffer::ReusePictureBuffer() { |
| 327 DCHECK_NE(UNUSED, state_); | 389 DCHECK_NE(UNUSED, state_); |
| 328 DCHECK(decoding_surface_); | 390 DCHECK(decoding_surface_); |
| 329 EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); | 391 EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); |
| 330 eglReleaseTexImage(egl_display, decoding_surface_, EGL_BACK_BUFFER); | 392 eglReleaseTexImage(egl_display, decoding_surface_, EGL_BACK_BUFFER); |
| 331 | 393 |
| 332 decoder_surface_.Release(); | 394 decoder_surface_.Release(); |
| 333 target_surface_.Release(); | 395 target_surface_.Release(); |
| 334 decoder_dx11_texture_.Release(); | 396 decoder_dx11_texture_.Release(); |
| 335 state_ = UNUSED; | 397 state_ = UNUSED; |
| 336 if (egl_keyed_mutex_) { | 398 if (egl_keyed_mutex_) { |
| 337 HRESULT hr = egl_keyed_mutex_->ReleaseSync(++keyed_mutex_value_); | 399 HRESULT hr = egl_keyed_mutex_->ReleaseSync(++keyed_mutex_value_); |
| 338 RETURN_ON_FAILURE(hr == S_OK, "Could not release sync mutex", false); | 400 RETURN_ON_FAILURE(hr == S_OK, "Could not release sync mutex", false); |
| 339 } | 401 } |
| 340 return true; | 402 return true; |
| 341 } | 403 } |
| 342 | 404 |
| 343 EGLStreamPictureBuffer::EGLStreamPictureBuffer(const PictureBuffer& buffer) | 405 EGLStreamPictureBuffer::EGLStreamPictureBuffer(const PictureBuffer& buffer) |
| 344 : DXVAPictureBuffer(buffer), stream_(nullptr) {} | 406 : DXVAPictureBuffer(buffer), stream_(nullptr) {} |
| 345 | 407 |
| 346 EGLStreamPictureBuffer::~EGLStreamPictureBuffer() { | 408 EGLStreamPictureBuffer::~EGLStreamPictureBuffer() { |
| 347 if (stream_) { | 409 // stream_ will be deleted by gl_image_. |
| 348 EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); | |
| 349 eglDestroyStreamKHR(egl_display, stream_); | |
| 350 stream_ = nullptr; | |
| 351 } | |
| 352 } | 410 } |
| 353 | 411 |
| 354 bool EGLStreamPictureBuffer::Initialize() { | 412 bool EGLStreamPictureBuffer::Initialize() { |
| 355 RETURN_ON_FAILURE(picture_buffer_.service_texture_ids().size() >= 2, | 413 RETURN_ON_FAILURE(picture_buffer_.service_texture_ids().size() >= 2, |
| 356 "Not enough texture ids provided", false); | 414 "Not enough texture ids provided", false); |
| 357 | 415 |
| 358 EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); | 416 EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); |
| 359 const EGLint stream_attributes[] = { | 417 const EGLint stream_attributes[] = { |
| 360 EGL_CONSUMER_LATENCY_USEC_KHR, | 418 EGL_CONSUMER_LATENCY_USEC_KHR, |
| 361 0, | 419 0, |
| 362 EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, | 420 EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, |
| 363 0, | 421 0, |
| 364 EGL_NONE, | 422 EGL_NONE, |
| 365 }; | 423 }; |
| 366 stream_ = eglCreateStreamKHR(egl_display, stream_attributes); | 424 stream_ = eglCreateStreamKHR(egl_display, stream_attributes); |
| 367 RETURN_ON_FAILURE(!!stream_, "Could not create stream", false); | 425 RETURN_ON_FAILURE(!!stream_, "Could not create stream", false); |
| 426 gl_image_ = make_scoped_refptr(new GLImageEGLStream(size(), stream_)); |
| 368 gl::ScopedActiveTexture texture0(GL_TEXTURE0); | 427 gl::ScopedActiveTexture texture0(GL_TEXTURE0); |
| 369 gl::ScopedTextureBinder texture0_binder( | 428 gl::ScopedTextureBinder texture0_binder( |
| 370 GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[0]); | 429 GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[0]); |
| 371 gl::ScopedActiveTexture texture1(GL_TEXTURE1); | 430 gl::ScopedActiveTexture texture1(GL_TEXTURE1); |
| 372 gl::ScopedTextureBinder texture1_binder( | 431 gl::ScopedTextureBinder texture1_binder( |
| 373 GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[1]); | 432 GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[1]); |
| 374 | 433 |
| 375 EGLAttrib consumer_attributes[] = { | 434 EGLAttrib consumer_attributes[] = { |
| 376 EGL_COLOR_BUFFER_TYPE, | 435 EGL_COLOR_BUFFER_TYPE, |
| 377 EGL_YUV_BUFFER_EXT, | 436 EGL_YUV_BUFFER_EXT, |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 result = eglStreamConsumerAcquireKHR(egl_display, stream_); | 505 result = eglStreamConsumerAcquireKHR(egl_display, stream_); |
| 447 RETURN_ON_FAILURE(result, "Could not post acquire stream", false); | 506 RETURN_ON_FAILURE(result, "Could not post acquire stream", false); |
| 448 return true; | 507 return true; |
| 449 } | 508 } |
| 450 | 509 |
| 451 EGLStreamCopyPictureBuffer::EGLStreamCopyPictureBuffer( | 510 EGLStreamCopyPictureBuffer::EGLStreamCopyPictureBuffer( |
| 452 const PictureBuffer& buffer) | 511 const PictureBuffer& buffer) |
| 453 : DXVAPictureBuffer(buffer), stream_(nullptr) {} | 512 : DXVAPictureBuffer(buffer), stream_(nullptr) {} |
| 454 | 513 |
| 455 EGLStreamCopyPictureBuffer::~EGLStreamCopyPictureBuffer() { | 514 EGLStreamCopyPictureBuffer::~EGLStreamCopyPictureBuffer() { |
| 456 if (stream_) { | 515 // stream_ will be deleted by gl_image_. |
| 457 EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); | |
| 458 eglDestroyStreamKHR(egl_display, stream_); | |
| 459 stream_ = nullptr; | |
| 460 } | |
| 461 } | 516 } |
| 462 | 517 |
| 463 bool EGLStreamCopyPictureBuffer::Initialize( | 518 bool EGLStreamCopyPictureBuffer::Initialize( |
| 464 const DXVAVideoDecodeAccelerator& decoder) { | 519 const DXVAVideoDecodeAccelerator& decoder) { |
| 465 RETURN_ON_FAILURE(picture_buffer_.service_texture_ids().size() >= 2, | 520 RETURN_ON_FAILURE(picture_buffer_.service_texture_ids().size() >= 2, |
| 466 "Not enough texture ids provided", false); | 521 "Not enough texture ids provided", false); |
| 467 | 522 |
| 468 EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); | 523 EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); |
| 469 const EGLint stream_attributes[] = { | 524 const EGLint stream_attributes[] = { |
| 470 EGL_CONSUMER_LATENCY_USEC_KHR, | 525 EGL_CONSUMER_LATENCY_USEC_KHR, |
| 471 0, | 526 0, |
| 472 EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, | 527 EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, |
| 473 0, | 528 0, |
| 474 EGL_NONE, | 529 EGL_NONE, |
| 475 }; | 530 }; |
| 476 stream_ = eglCreateStreamKHR(egl_display, stream_attributes); | 531 stream_ = eglCreateStreamKHR(egl_display, stream_attributes); |
| 477 RETURN_ON_FAILURE(!!stream_, "Could not create stream", false); | 532 RETURN_ON_FAILURE(!!stream_, "Could not create stream", false); |
| 533 gl_image_ = make_scoped_refptr(new GLImageEGLStream(size(), stream_)); |
| 478 gl::ScopedActiveTexture texture0(GL_TEXTURE0); | 534 gl::ScopedActiveTexture texture0(GL_TEXTURE0); |
| 479 gl::ScopedTextureBinder texture0_binder( | 535 gl::ScopedTextureBinder texture0_binder( |
| 480 GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[0]); | 536 GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[0]); |
| 481 gl::ScopedActiveTexture texture1(GL_TEXTURE1); | 537 gl::ScopedActiveTexture texture1(GL_TEXTURE1); |
| 482 gl::ScopedTextureBinder texture1_binder( | 538 gl::ScopedTextureBinder texture1_binder( |
| 483 GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[1]); | 539 GL_TEXTURE_EXTERNAL_OES, picture_buffer_.service_texture_ids()[1]); |
| 484 | 540 |
| 485 EGLAttrib consumer_attributes[] = { | 541 EGLAttrib consumer_attributes[] = { |
| 486 EGL_COLOR_BUFFER_TYPE, | 542 EGL_COLOR_BUFFER_TYPE, |
| 487 EGL_YUV_BUFFER_EXT, | 543 EGL_YUV_BUFFER_EXT, |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 603 state_ = UNUSED; | 659 state_ = UNUSED; |
| 604 | 660 |
| 605 if (stream_) { | 661 if (stream_) { |
| 606 EGLBoolean result = eglStreamConsumerReleaseKHR(egl_display, stream_); | 662 EGLBoolean result = eglStreamConsumerReleaseKHR(egl_display, stream_); |
| 607 RETURN_ON_FAILURE(result, "Could not release stream", false); | 663 RETURN_ON_FAILURE(result, "Could not release stream", false); |
| 608 } | 664 } |
| 609 return true; | 665 return true; |
| 610 } | 666 } |
| 611 | 667 |
| 612 } // namespace media | 668 } // namespace media |
| OLD | NEW |