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