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 
5 #include "gpu/ipc/service/gpu_memory_buffer_factory_dxgi.h"
6 #include <wrl.h>
7 #include <vector>
8 #include "base/trace_event/trace_event.h"
9 #include "ui/gfx/buffer_format_util.h"
10 #include "ui/gl/gl_angle_util_win.h"
11 #include "ui/gl/gl_bindings.h"
12 #include "ui/gl/gl_image_dxgi.h"
13 
14 namespace gpu {
15 
GpuMemoryBufferFactoryDXGI()16 GpuMemoryBufferFactoryDXGI::GpuMemoryBufferFactoryDXGI() {}
17 
~GpuMemoryBufferFactoryDXGI()18 GpuMemoryBufferFactoryDXGI::~GpuMemoryBufferFactoryDXGI() {}
19 
CreateGpuMemoryBuffer(gfx::GpuMemoryBufferId id,const gfx::Size & size,gfx::BufferFormat format,gfx::BufferUsage usage,int client_id,SurfaceHandle surface_handle)20 gfx::GpuMemoryBufferHandle GpuMemoryBufferFactoryDXGI::CreateGpuMemoryBuffer(
21     gfx::GpuMemoryBufferId id,
22     const gfx::Size& size,
23     gfx::BufferFormat format,
24     gfx::BufferUsage usage,
25     int client_id,
26     SurfaceHandle surface_handle) {
27   TRACE_EVENT0("gpu", "GpuMemoryBufferFactoryDXGI::CreateGpuMemoryBuffer");
28 
29   gfx::GpuMemoryBufferHandle handle;
30 
31   Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device =
32       gl::QueryD3D11DeviceObjectFromANGLE();
33   if (!d3d11_device)
34     return handle;
35 
36   DXGI_FORMAT dxgi_format;
37   switch (format) {
38     case gfx::BufferFormat::RGBA_8888:
39     case gfx::BufferFormat::RGBX_8888:
40       dxgi_format = DXGI_FORMAT_R8G8B8A8_UNORM;
41       break;
42     default:
43       NOTREACHED();
44       return handle;
45   }
46 
47   // We are binding as a shader resource and render target regardless of usage,
48   // so make sure that the usage is one that we support.
49   DCHECK(usage == gfx::BufferUsage::GPU_READ ||
50          usage == gfx::BufferUsage::SCANOUT);
51 
52   D3D11_TEXTURE2D_DESC desc = {
53       size.width(),
54       size.height(),
55       1,
56       1,
57       dxgi_format,
58       {1, 0},
59       D3D11_USAGE_DEFAULT,
60       D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET,
61       0,
62       D3D11_RESOURCE_MISC_SHARED_NTHANDLE |
63           D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX};
64 
65   Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture;
66 
67   if (FAILED(d3d11_device->CreateTexture2D(&desc, nullptr,
68                                            d3d11_texture.GetAddressOf())))
69     return handle;
70 
71   Microsoft::WRL::ComPtr<IDXGIResource1> dxgi_resource;
72   if (FAILED(d3d11_texture.CopyTo(dxgi_resource.GetAddressOf())))
73     return handle;
74 
75   HANDLE texture_handle;
76   if (FAILED(dxgi_resource->CreateSharedHandle(
77           nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
78           nullptr, &texture_handle)))
79     return handle;
80 
81   size_t buffer_size;
82   if (!BufferSizeForBufferFormatChecked(size, format, &buffer_size))
83     return handle;
84 
85   handle.dxgi_handle.Set(texture_handle);
86   handle.type = gfx::DXGI_SHARED_HANDLE;
87   handle.id = id;
88 
89   return handle;
90 }
91 
DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,int client_id)92 void GpuMemoryBufferFactoryDXGI::DestroyGpuMemoryBuffer(
93     gfx::GpuMemoryBufferId id,
94     int client_id) {}
95 
AsImageFactory()96 ImageFactory* GpuMemoryBufferFactoryDXGI::AsImageFactory() {
97   return this;
98 }
99 
100 scoped_refptr<gl::GLImage>
CreateImageForGpuMemoryBuffer(gfx::GpuMemoryBufferHandle handle,const gfx::Size & size,gfx::BufferFormat format,int client_id,SurfaceHandle surface_handle)101 GpuMemoryBufferFactoryDXGI::CreateImageForGpuMemoryBuffer(
102     gfx::GpuMemoryBufferHandle handle,
103     const gfx::Size& size,
104     gfx::BufferFormat format,
105     int client_id,
106     SurfaceHandle surface_handle) {
107   if (handle.type != gfx::DXGI_SHARED_HANDLE)
108     return nullptr;
109   // Transfer ownership of handle to GLImageDXGI.
110   auto image = base::MakeRefCounted<gl::GLImageDXGI>(size, nullptr);
111   if (!image->InitializeHandle(std::move(handle.dxgi_handle), 0, format))
112     return nullptr;
113   return image;
114 }
115 
RequiredTextureType()116 unsigned GpuMemoryBufferFactoryDXGI::RequiredTextureType() {
117   return GL_TEXTURE_2D;
118 }
119 
SupportsFormatRGB()120 bool GpuMemoryBufferFactoryDXGI::SupportsFormatRGB() {
121   return true;
122 }
123 }  // namespace gpu
124