1 /*
2  * Copyright 2019 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/core/SkSurface.h"
9 #include "include/gpu/GrBackendSurface.h"
10 #include "include/gpu/GrContext.h"
11 #include "src/core/SkAutoMalloc.h"
12 #include "tools/sk_app/DawnWindowContext.h"
13 
14 #include "dawn/dawn_proc.h"
15 
16 static wgpu::TextureUsage kUsage = wgpu::TextureUsage::OutputAttachment |
17                                    wgpu::TextureUsage::CopySrc;
18 
PrintDeviceError(WGPUErrorType,const char * message,void *)19 static void PrintDeviceError(WGPUErrorType, const char* message, void*) {
20     printf("Device error: %s\n", message);
21     SkASSERT(false);
22 }
23 
24 namespace sk_app {
25 
DawnWindowContext(const DisplayParams & params,wgpu::TextureFormat swapChainFormat)26 DawnWindowContext::DawnWindowContext(const DisplayParams& params,
27                                      wgpu::TextureFormat swapChainFormat)
28     : WindowContext(params)
29     , fSwapChainFormat(swapChainFormat)
30     , fInstance(std::make_unique<dawn_native::Instance>()) {
31 }
32 
initializeContext(int width,int height)33 void DawnWindowContext::initializeContext(int width, int height) {
34     fWidth = width;
35     fHeight = height;
36     fDevice = onInitializeContext();
37     fContext = GrContext::MakeDawn(fDevice, fDisplayParams.fGrContextOptions);
38 
39     if (!fContext) {
40         return;
41     }
42     fSwapChainImplementation = this->createSwapChainImplementation(-1, -1, fDisplayParams);
43     wgpu::SwapChainDescriptor swapChainDesc;
44     swapChainDesc.implementation = reinterpret_cast<int64_t>(&fSwapChainImplementation);
45     fSwapChain = fDevice.CreateSwapChain(nullptr, &swapChainDesc);
46     if (!fSwapChain) {
47         fContext.reset();
48         return;
49     }
50     fSwapChain.Configure(fSwapChainFormat, kUsage, width, height);
51     fDevice.SetUncapturedErrorCallback(PrintDeviceError, 0);
52 }
53 
~DawnWindowContext()54 DawnWindowContext::~DawnWindowContext() {
55 }
56 
destroyContext()57 void DawnWindowContext::destroyContext() {
58     if (!fDevice.Get()) {
59         return;
60     }
61 
62     this->onDestroyContext();
63 
64     fContext.reset();
65     fDevice = nullptr;
66 }
67 
getBackbufferSurface()68 sk_sp<SkSurface> DawnWindowContext::getBackbufferSurface() {
69     GrDawnRenderTargetInfo rtInfo;
70     rtInfo.fTextureView = fSwapChain.GetCurrentTextureView();
71     rtInfo.fFormat = fSwapChainFormat;
72     rtInfo.fLevelCount = 1; // FIXME
73     GrBackendRenderTarget backendRenderTarget(fWidth, fHeight, fDisplayParams.fMSAASampleCount, 8,
74                                               rtInfo);
75     fSurface = SkSurface::MakeFromBackendRenderTarget(fContext.get(),
76                                                       backendRenderTarget,
77                                                       this->getRTOrigin(),
78                                                       fDisplayParams.fColorType,
79                                                       fDisplayParams.fColorSpace,
80                                                       &fDisplayParams.fSurfaceProps);
81     return fSurface;
82 }
83 
swapBuffers()84 void DawnWindowContext::swapBuffers() {
85     fSwapChain.Present();
86     this->onSwapBuffers();
87 }
88 
resize(int w,int h)89 void DawnWindowContext::resize(int w, int h) {
90     fWidth = w;
91     fHeight = h;
92     fSwapChainImplementation = this->createSwapChainImplementation(w, h, fDisplayParams);
93     wgpu::SwapChainDescriptor swapChainDesc;
94     swapChainDesc.implementation = reinterpret_cast<int64_t>(&fSwapChainImplementation);
95     fSwapChain = fDevice.CreateSwapChain(nullptr, &swapChainDesc);
96     if (!fSwapChain) {
97         fContext.reset();
98         return;
99     }
100     fSwapChain.Configure(fSwapChainFormat, kUsage, fWidth, fHeight);
101 }
102 
setDisplayParams(const DisplayParams & params)103 void DawnWindowContext::setDisplayParams(const DisplayParams& params) {
104     fDisplayParams = params;
105 }
106 
createDevice(dawn_native::BackendType type)107 wgpu::Device DawnWindowContext::createDevice(dawn_native::BackendType type) {
108     fInstance->DiscoverDefaultAdapters();
109     DawnProcTable backendProcs = dawn_native::GetProcs();
110     dawnProcSetProcs(&backendProcs);
111 
112     std::vector<dawn_native::Adapter> adapters = fInstance->GetAdapters();
113     for (dawn_native::Adapter adapter : adapters) {
114         if (adapter.GetBackendType() == type) {
115             return adapter.CreateDevice();
116         }
117     }
118     return nullptr;
119 }
120 
121 }   //namespace sk_app
122