| // Copyright 2017 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 "ui/gl/gl_image_dxgi.h" |
| |
| #include "third_party/khronos/EGL/egl.h" |
| #include "third_party/khronos/EGL/eglext.h" |
| #include "ui/gl/gl_bindings.h" |
| #include "ui/gl/gl_image.h" |
| #include "ui/gl/gl_surface_egl.h" |
| |
| namespace gl { |
| |
| GLImageDXGI::GLImageDXGI(const gfx::Size& size, EGLStreamKHR stream) |
| : size_(size), stream_(stream) {} |
| |
| // static |
| GLImageDXGI* GLImageDXGI::FromGLImage(GLImage* image) { |
| if (!image || image->GetType() != Type::DXGI_IMAGE) |
| return nullptr; |
| return static_cast<GLImageDXGI*>(image); |
| } |
| |
| gfx::Size GLImageDXGI::GetSize() { |
| return size_; |
| } |
| |
| unsigned GLImageDXGI::GetInternalFormat() { |
| return GL_BGRA_EXT; |
| } |
| |
| bool GLImageDXGI::BindTexImage(unsigned target) { |
| return true; |
| } |
| |
| void GLImageDXGI::ReleaseTexImage(unsigned target) {} |
| |
| bool GLImageDXGI::CopyTexImage(unsigned target) { |
| return false; |
| } |
| |
| bool GLImageDXGI::CopyTexSubImage(unsigned target, |
| const gfx::Point& offset, |
| const gfx::Rect& rect) { |
| return false; |
| } |
| |
| bool GLImageDXGI::ScheduleOverlayPlane(gfx::AcceleratedWidget widget, |
| int z_order, |
| gfx::OverlayTransform transform, |
| const gfx::Rect& bounds_rect, |
| const gfx::RectF& crop_rect) { |
| return false; |
| } |
| |
| void GLImageDXGI::Flush() {} |
| |
| void GLImageDXGI::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd, |
| uint64_t process_tracing_id, |
| const std::string& dump_name) {} |
| |
| GLImage::Type GLImageDXGI::GetType() const { |
| return Type::DXGI_IMAGE; |
| } |
| |
| void GLImageDXGI::SetTexture( |
| const base::win::ScopedComPtr<ID3D11Texture2D>& texture, |
| size_t level) { |
| texture_ = texture; |
| level_ = level; |
| } |
| |
| GLImageDXGI::~GLImageDXGI() { |
| EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); |
| eglDestroyStreamKHR(egl_display, stream_); |
| } |
| |
| CopyingGLImageDXGI::CopyingGLImageDXGI( |
| const base::win::ScopedComPtr<ID3D11Device>& d3d11_device, |
| const gfx::Size& size, |
| EGLStreamKHR stream) |
| : GLImageDXGI(size, stream), d3d11_device_(d3d11_device) {} |
| |
| bool CopyingGLImageDXGI::Initialize() { |
| D3D11_TEXTURE2D_DESC desc; |
| desc.Width = size_.width(); |
| desc.Height = size_.height(); |
| desc.MipLevels = 1; |
| desc.ArraySize = 1; |
| desc.Format = DXGI_FORMAT_NV12; |
| desc.SampleDesc.Count = 1; |
| desc.SampleDesc.Quality = 0; |
| desc.Usage = D3D11_USAGE_DEFAULT; |
| desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; |
| desc.CPUAccessFlags = 0; |
| desc.MiscFlags = 0; |
| |
| HRESULT hr = d3d11_device_->CreateTexture2D( |
| &desc, nullptr, decoder_copy_texture_.GetAddressOf()); |
| CHECK(SUCCEEDED(hr)); |
| EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay(); |
| |
| EGLAttrib frame_attributes[] = { |
| EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE, 0, EGL_NONE, |
| }; |
| |
| EGLBoolean result = eglStreamPostD3DTextureNV12ANGLE( |
| egl_display, stream_, static_cast<void*>(decoder_copy_texture_.Get()), |
| frame_attributes); |
| if (!result) |
| return false; |
| result = eglStreamConsumerAcquireKHR(egl_display, stream_); |
| if (!result) |
| return false; |
| |
| d3d11_device_.CopyTo(video_device_.GetAddressOf()); |
| base::win::ScopedComPtr<ID3D11DeviceContext> context; |
| d3d11_device_->GetImmediateContext(context.GetAddressOf()); |
| context.CopyTo(video_context_.GetAddressOf()); |
| |
| base::win::ScopedComPtr<ID3D10Multithread> multithread; |
| d3d11_device_.CopyTo(multithread.GetAddressOf()); |
| CHECK(multithread->GetMultithreadProtected()); |
| return true; |
| } |
| |
| bool CopyingGLImageDXGI::InitializeVideoProcessor( |
| const base::win::ScopedComPtr<ID3D11VideoProcessor>& video_processor, |
| const base::win::ScopedComPtr<ID3D11VideoProcessorEnumerator>& enumerator) { |
| output_view_.Reset(); |
| |
| base::win::ScopedComPtr<ID3D11Device> processor_device; |
| video_processor->GetDevice(processor_device.GetAddressOf()); |
| CHECK_EQ(d3d11_device_.Get(), processor_device.Get()); |
| |
| d3d11_processor_ = video_processor; |
| enumerator_ = enumerator; |
| D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC output_view_desc = { |
| D3D11_VPOV_DIMENSION_TEXTURE2D}; |
| output_view_desc.Texture2D.MipSlice = 0; |
| base::win::ScopedComPtr<ID3D11VideoProcessorOutputView> output_view; |
| HRESULT hr = video_device_->CreateVideoProcessorOutputView( |
| decoder_copy_texture_.Get(), enumerator_.Get(), &output_view_desc, |
| output_view_.GetAddressOf()); |
| if (FAILED(hr)) { |
| DLOG(ERROR) << "Failed to get output view"; |
| return false; |
| } |
| return true; |
| } |
| |
| void CopyingGLImageDXGI::UnbindFromTexture() { |
| copied_ = false; |
| } |
| |
| bool CopyingGLImageDXGI::BindTexImage(unsigned target) { |
| if (copied_) |
| return true; |
| |
| CHECK(video_device_); |
| base::win::ScopedComPtr<ID3D11Device> texture_device; |
| texture_->GetDevice(texture_device.GetAddressOf()); |
| CHECK_EQ(d3d11_device_.Get(), texture_device.Get()); |
| |
| D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC input_view_desc = {0}; |
| input_view_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D; |
| input_view_desc.Texture2D.ArraySlice = (UINT)level_; |
| input_view_desc.Texture2D.MipSlice = 0; |
| base::win::ScopedComPtr<ID3D11VideoProcessorInputView> input_view; |
| HRESULT hr = video_device_->CreateVideoProcessorInputView( |
| texture_.Get(), enumerator_.Get(), &input_view_desc, |
| input_view.GetAddressOf()); |
| if (FAILED(hr)) { |
| DLOG(ERROR) << "Failed to create video processor input view."; |
| return false; |
| } |
| |
| D3D11_VIDEO_PROCESSOR_STREAM streams = {0}; |
| streams.Enable = TRUE; |
| streams.pInputSurface = input_view.Get(); |
| |
| hr = video_context_->VideoProcessorBlt(d3d11_processor_.Get(), |
| output_view_.Get(), 0, 1, &streams); |
| if (FAILED(hr)) { |
| DLOG(ERROR) << "Failed to process video"; |
| return false; |
| } |
| copied_ = true; |
| return true; |
| } |
| |
| CopyingGLImageDXGI::~CopyingGLImageDXGI() {} |
| |
| } // namespace gl |