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