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/callback_helpers.h"
9 #include "base/command_line.h"
10 #include "base/logging.h"
11 #include "base/memory/ptr_util.h"
12 #include "gpu/ipc/common/gpu_memory_buffer_impl_dxgi.h"
13 #include "gpu/ipc/common/gpu_memory_buffer_support.h"
14 #include "ui/gfx/buffer_format_util.h"
15 #include "ui/gl/gl_angle_util_win.h"
16 #include "ui/gl/gl_switches.h"
17
18 namespace gpu {
19
~GpuMemoryBufferImplDXGI()20 GpuMemoryBufferImplDXGI::~GpuMemoryBufferImplDXGI() {}
21
22 std::unique_ptr<GpuMemoryBufferImplDXGI>
CreateFromHandle(gfx::GpuMemoryBufferHandle handle,const gfx::Size & size,gfx::BufferFormat format,gfx::BufferUsage usage,DestructionCallback callback)23 GpuMemoryBufferImplDXGI::CreateFromHandle(gfx::GpuMemoryBufferHandle handle,
24 const gfx::Size& size,
25 gfx::BufferFormat format,
26 gfx::BufferUsage usage,
27 DestructionCallback callback) {
28 DCHECK(handle.dxgi_handle.IsValid());
29 return base::WrapUnique(
30 new GpuMemoryBufferImplDXGI(handle.id, size, format, std::move(callback),
31 std::move(handle.dxgi_handle)));
32 }
33
AllocateForTesting(const gfx::Size & size,gfx::BufferFormat format,gfx::BufferUsage usage,gfx::GpuMemoryBufferHandle * handle)34 base::OnceClosure GpuMemoryBufferImplDXGI::AllocateForTesting(
35 const gfx::Size& size,
36 gfx::BufferFormat format,
37 gfx::BufferUsage usage,
38 gfx::GpuMemoryBufferHandle* handle) {
39 // This test only works with hardware rendering.
40 DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
41 switches::kUseGpuInTests));
42
43 Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
44 gl::QueryD3D11DeviceObjectFromANGLE();
45
46 DCHECK(format == gfx::BufferFormat::RGBA_8888 ||
47 format == gfx::BufferFormat::RGBX_8888);
48 DCHECK(usage == gfx::BufferUsage::GPU_READ ||
49 usage == gfx::BufferUsage::SCANOUT);
50
51 D3D11_TEXTURE2D_DESC desc = {
52 size.width(),
53 size.height(),
54 1,
55 1,
56 DXGI_FORMAT_R8G8B8A8_UNORM,
57 {1, 0},
58 D3D11_USAGE_DEFAULT,
59 D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET,
60 0,
61 D3D11_RESOURCE_MISC_SHARED_NTHANDLE |
62 D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX};
63
64 Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture;
65
66 HRESULT hr = d3d11_device->CreateTexture2D(&desc, nullptr, &d3d11_texture);
67 DCHECK(SUCCEEDED(hr));
68
69 Microsoft::WRL::ComPtr<IDXGIResource1> dxgi_resource;
70 hr = d3d11_texture.As(&dxgi_resource);
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