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