1 /*
2  * Copyright 2017 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 #ifndef GrMtlGpu_DEFINED
9 #define GrMtlGpu_DEFINED
10 
11 #include "GrGpu.h"
12 #include "GrRenderTarget.h"
13 #include "GrSemaphore.h"
14 #include "GrTexture.h"
15 
16 #include "GrMtlCaps.h"
17 #include "GrMtlCopyManager.h"
18 #include "GrMtlResourceProvider.h"
19 #include "GrMtlStencilAttachment.h"
20 
21 #import <Metal/Metal.h>
22 
23 class GrMtlGpuRTCommandBuffer;
24 class GrMtlTexture;
25 class GrSemaphore;
26 struct GrMtlBackendContext;
27 
28 namespace SkSL {
29     class Compiler;
30 }
31 
32 class GrMtlGpu : public GrGpu {
33 public:
34     static sk_sp<GrGpu> Make(GrContext* context, const GrContextOptions& options,
35                              id<MTLDevice> device, id<MTLCommandQueue> queue);
36 
37     ~GrMtlGpu() override = default;
38 
39     const GrMtlCaps& mtlCaps() const { return *fMtlCaps.get(); }
40 
41     id<MTLDevice> device() const { return fDevice; }
42 
43     id<MTLCommandBuffer> commandBuffer() const { return fCmdBuffer; }
44 
45     GrMtlResourceProvider& resourceProvider() { return fResourceProvider; }
46 
47     enum SyncQueue {
48         kForce_SyncQueue,
49         kSkip_SyncQueue
50     };
51 
52     // Commits the current command buffer to the queue and then creates a new command buffer. If
53     // sync is set to kForce_SyncQueue, the function will wait for all work in the committed
54     // command buffer to finish before creating a new buffer and returning.
55     void submitCommandBuffer(SyncQueue sync);
56 
57 #ifdef GR_TEST_UTILS
58     GrBackendTexture createTestingOnlyBackendTexture(const void* pixels, int w, int h,
59                                                      GrColorType colorType, bool isRT,
60                                                      GrMipMapped, size_t rowBytes = 0) override;
61 
62     bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
63 
64     void deleteTestingOnlyBackendTexture(const GrBackendTexture&) override;
65 
66     GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType) override;
67 
68     void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
69 
70     void testingOnly_flushGpuAndSync() override;
71 #endif
72 
73     bool copySurfaceAsBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin,
74                            GrSurface* src, GrSurfaceOrigin srcOrigin,
75                            const SkIRect& srcRect, const SkIPoint& dstPoint);
76 
77     // This function is needed when we want to copy between two surfaces with different origins and
78     // the destination surface is not a render target. We will first draw to a temporary render
79     // target to adjust for the different origins and then blit from there to the destination.
80     bool copySurfaceAsDrawThenBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin,
81                                    GrSurface* src, GrSurfaceOrigin srcOrigin,
82                                    const SkIRect& srcRect, const SkIPoint& dstPoint);
83 
84     bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
85                        GrSurface* src, GrSurfaceOrigin srcOrigin,
86                        const SkIRect& srcRect,
87                        const SkIPoint& dstPoint,
88                        bool canDiscardOutsideDstRect) override;
89 
90     GrGpuRTCommandBuffer* getCommandBuffer(
91                                     GrRenderTarget*, GrSurfaceOrigin, const SkRect& bounds,
92                                     const GrGpuRTCommandBuffer::LoadAndStoreInfo&,
93                                     const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&) override;
94 
95     GrGpuTextureCommandBuffer* getCommandBuffer(GrTexture*, GrSurfaceOrigin) override;
96 
97     SkSL::Compiler* shaderCompiler() const { return fCompiler.get(); }
98 
99     void submit(GrGpuCommandBuffer* buffer) override;
100 
101     GrFence SK_WARN_UNUSED_RESULT insertFence() override { return 0; }
102     bool waitFence(GrFence, uint64_t) override { return true; }
103     void deleteFence(GrFence) const override {}
104 
105     sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned) override {
106         return nullptr;
107     }
108     sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
109                                             GrResourceProvider::SemaphoreWrapType wrapType,
110                                             GrWrapOwnership ownership) override { return nullptr; }
111     void insertSemaphore(sk_sp<GrSemaphore> semaphore) override {}
112     void waitSemaphore(sk_sp<GrSemaphore> semaphore) override {}
113     sk_sp<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override { return nullptr; }
114 
115     // When the Metal backend actually uses indirect command buffers, this function will actually do
116     // what it says. For now, every command is encoded directly into the primary command buffer, so
117     // this function is pretty useless, except for indicating that a render target has been drawn
118     // to.
119     void submitIndirectCommandBuffer(GrSurface* surface, GrSurfaceOrigin origin,
120                                      const SkIRect* bounds) {
121         this->didWriteToSurface(surface, origin, bounds);
122     }
123 
124 private:
125     GrMtlGpu(GrContext* context, const GrContextOptions& options,
126              id<MTLDevice> device, id<MTLCommandQueue> queue, MTLFeatureSet featureSet);
127 
128     void onResetContext(uint32_t resetBits) override {}
129 
130     void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
131 
132     sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
133                                      const GrMipLevel texels[], int mipLevelCount) override;
134 
135     sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrWrapCacheable,
136                                           GrIOType) override;
137 
138     sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&, int sampleCnt,
139                                                     GrWrapOwnership, GrWrapCacheable) override;
140 
141     sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&) override;
142 
143     sk_sp<GrRenderTarget> onWrapBackendTextureAsRenderTarget(const GrBackendTexture&,
144                                                              int sampleCnt) override;
145 
146     sk_sp<GrBuffer> onCreateBuffer(size_t, GrBufferType, GrAccessPattern, const void*) override;
147 
148     bool onReadPixels(GrSurface* surface, int left, int top, int width, int height, GrColorType,
149                       void* buffer, size_t rowBytes) override;
150 
151     bool onWritePixels(GrSurface*, int left, int top, int width, int height, GrColorType,
152                        const GrMipLevel[], int mipLevelCount) override;
153 
154     bool onTransferPixels(GrTexture*,
155                           int left, int top, int width, int height,
156                           GrColorType, GrBuffer*,
157                           size_t offset, size_t rowBytes) override {
158         return false;
159     }
160 
161     bool onRegenerateMipMapLevels(GrTexture*) override { return false; }
162 
163     void onResolveRenderTarget(GrRenderTarget* target) override { return; }
164 
165     void onFinishFlush(bool insertedSemaphores) override {
166         this->submitCommandBuffer(kSkip_SyncQueue);
167     }
168 
169     // Function that uploads data onto textures with private storage mode (GPU access only).
170     bool uploadToTexture(GrMtlTexture* tex, int left, int top, int width, int height,
171                          GrColorType dataColorType, const GrMipLevel texels[], int mipLevels);
172 
173     GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget*,
174                                                                 int width,
175                                                                 int height) override;
176 
177 #if GR_TEST_UTILS
178     bool createTestingOnlyMtlTextureInfo(GrColorType colorType, int w, int h, bool texturable,
179                                          bool renderable, GrMipMapped mipMapped,
180                                          const void* srcData, size_t rowBytes,
181                                          GrMtlTextureInfo* info);
182 #endif
183 
184     sk_sp<GrMtlCaps> fMtlCaps;
185 
186     id<MTLDevice> fDevice;
187     id<MTLCommandQueue> fQueue;
188 
189     id<MTLCommandBuffer> fCmdBuffer;
190 
191     std::unique_ptr<SkSL::Compiler> fCompiler;
192     GrMtlCopyManager fCopyManager;
193     GrMtlResourceProvider fResourceProvider;
194 
195     typedef GrGpu INHERITED;
196 };
197 
198 #endif
199 
200