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