1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 #include <d3d11.h>
5 #include <wrl.h>
6 
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/command_line.h"
10 #include "base/memory/ptr_util.h"
11 #include "gpu/ipc/common/gpu_memory_buffer_impl_dxgi.h"
12 #include "gpu/ipc/common/gpu_memory_buffer_support.h"
13 #include "ui/gfx/buffer_format_util.h"
14 #include "ui/gl/gl_angle_util_win.h"
15 #include "ui/gl/gl_switches.h"
16 
17 namespace gpu {
18 
~GpuMemoryBufferImplDXGI()19 GpuMemoryBufferImplDXGI::~GpuMemoryBufferImplDXGI() {}
20 
21 std::unique_ptr<GpuMemoryBufferImplDXGI>
CreateFromHandle(gfx::GpuMemoryBufferHandle handle,const gfx::Size & size,gfx::BufferFormat format,gfx::BufferUsage usage,DestructionCallback callback)22 GpuMemoryBufferImplDXGI::CreateFromHandle(gfx::GpuMemoryBufferHandle handle,
23                                           const gfx::Size& size,
24                                           gfx::BufferFormat format,
25                                           gfx::BufferUsage usage,
26                                           DestructionCallback callback) {
27   DCHECK(handle.dxgi_handle.IsValid());
28   return base::WrapUnique(
29       new GpuMemoryBufferImplDXGI(handle.id, size, format, std::move(callback),
30                                   std::move(handle.dxgi_handle)));
31 }
32 
AllocateForTesting(const gfx::Size & size,gfx::BufferFormat format,gfx::BufferUsage usage,gfx::GpuMemoryBufferHandle * handle)33 base::OnceClosure GpuMemoryBufferImplDXGI::AllocateForTesting(
34     const gfx::Size& size,
35     gfx::BufferFormat format,
36     gfx::BufferUsage usage,
37     gfx::GpuMemoryBufferHandle* handle) {
38   // This test only works with hardware rendering.
39   DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
40       switches::kUseGpuInTests));
41 
42   Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
43       gl::QueryD3D11DeviceObjectFromANGLE();
44 
45   DCHECK(format == gfx::BufferFormat::RGBA_8888 ||
46          format == gfx::BufferFormat::RGBX_8888);
47   DCHECK(usage == gfx::BufferUsage::GPU_READ ||
48          usage == gfx::BufferUsage::SCANOUT);
49 
50   D3D11_TEXTURE2D_DESC desc = {
51       size.width(),
52       size.height(),
53       1,
54       1,
55       DXGI_FORMAT_R8G8B8A8_UNORM,
56       {1, 0},
57       D3D11_USAGE_DEFAULT,
58       D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET,
59       0,
60       D3D11_RESOURCE_MISC_SHARED_NTHANDLE |
61           D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX};
62 
63   Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture;
64 
65   HRESULT hr = d3d11_device->CreateTexture2D(&desc, nullptr,
66                                              d3d11_texture.GetAddressOf());
67   DCHECK(SUCCEEDED(hr));
68 
69   Microsoft::WRL::ComPtr<IDXGIResource1> dxgi_resource;
70   hr = d3d11_texture.CopyTo(dxgi_resource.GetAddressOf());
71   DCHECK(SUCCEEDED(hr));
72 
73   HANDLE texture_handle;
74   hr = dxgi_resource->CreateSharedHandle(
75       nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, nullptr,
76       &texture_handle);
77   DCHECK(SUCCEEDED(hr));
78 
79   gfx::GpuMemoryBufferId kBufferId(1);
80   handle->dxgi_handle.Set(texture_handle);
81   handle->type = gfx::DXGI_SHARED_HANDLE;
82   handle->id = kBufferId;
83   return base::DoNothing();
84 }
85 
Map()86 bool GpuMemoryBufferImplDXGI::Map() {
87   return false;  // The current implementation doesn't support mapping.
88 }
89 
memory(size_t plane)90 void* GpuMemoryBufferImplDXGI::memory(size_t plane) {
91   return nullptr;  // The current implementation doesn't support mapping.
92 }
93 
Unmap()94 void GpuMemoryBufferImplDXGI::Unmap() {}
95 
stride(size_t plane) const96 int GpuMemoryBufferImplDXGI::stride(size_t plane) const {
97   return gfx::RowSizeForBufferFormat(size_.width(), format_, plane);
98 }
99 
GetType() const100 gfx::GpuMemoryBufferType GpuMemoryBufferImplDXGI::GetType() const {
101   return gfx::DXGI_SHARED_HANDLE;
102 }
103 
CloneHandle() const104 gfx::GpuMemoryBufferHandle GpuMemoryBufferImplDXGI::CloneHandle() const {
105   gfx::GpuMemoryBufferHandle handle;
106   handle.type = gfx::DXGI_SHARED_HANDLE;
107   handle.id = id_;
108   handle.offset = 0;
109   handle.stride = stride(0);
110   base::ProcessHandle process = ::GetCurrentProcess();
111   HANDLE duplicated_handle;
112   BOOL result =
113       ::DuplicateHandle(process, dxgi_handle_.Get(), process,
114                         &duplicated_handle, 0, FALSE, DUPLICATE_SAME_ACCESS);
115   if (!result)
116     DPLOG(ERROR) << "Failed to duplicate DXGI resource handle.";
117   handle.dxgi_handle.Set(duplicated_handle);
118   return handle;
119 }
120 
GpuMemoryBufferImplDXGI(gfx::GpuMemoryBufferId id,const gfx::Size & size,gfx::BufferFormat format,DestructionCallback callback,base::win::ScopedHandle dxgi_handle)121 GpuMemoryBufferImplDXGI::GpuMemoryBufferImplDXGI(
122     gfx::GpuMemoryBufferId id,
123     const gfx::Size& size,
124     gfx::BufferFormat format,
125     DestructionCallback callback,
126     base::win::ScopedHandle dxgi_handle)
127     : GpuMemoryBufferImpl(id, size, format, std::move(callback)),
128       dxgi_handle_(std::move(dxgi_handle)) {}
129 
130 }  // namespace gpu
131