• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "include/core/SkTypes.h"
9 
10 #if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
11 #define GL_GLEXT_PROTOTYPES
12 #define EGL_EGLEXT_PROTOTYPES
13 
14 
15 #include "src/gpu/GrAHardwareBufferImageGenerator.h"
16 
17 #include <android/hardware_buffer.h>
18 
19 #include "include/gpu/GrBackendSurface.h"
20 #include "include/gpu/GrDirectContext.h"
21 #include "include/gpu/GrRecordingContext.h"
22 #include "include/gpu/gl/GrGLTypes.h"
23 #include "src/core/SkMessageBus.h"
24 #include "src/gpu/GrAHardwareBufferUtils.h"
25 #include "src/gpu/GrDirectContextPriv.h"
26 #include "src/gpu/GrProxyProvider.h"
27 #include "src/gpu/GrRecordingContextPriv.h"
28 #include "src/gpu/GrResourceCache.h"
29 #include "src/gpu/GrResourceProvider.h"
30 #include "src/gpu/GrResourceProviderPriv.h"
31 #include "src/gpu/GrTexture.h"
32 #include "src/gpu/GrTextureProxy.h"
33 #include "src/gpu/SkGr.h"
34 #include "src/gpu/gl/GrGLDefines.h"
35 
36 #include <EGL/egl.h>
37 #include <EGL/eglext.h>
38 #include <GLES/gl.h>
39 #include <GLES/glext.h>
40 
41 #ifdef SK_VULKAN
42 #include "include/gpu/vk/GrVkExtensions.h"
43 #include "src/gpu/vk/GrVkGpu.h"
44 #endif
45 
46 #define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
47 #define EGL_PROTECTED_CONTENT_EXT 0x32C0
48 
Make(AHardwareBuffer * graphicBuffer,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace,GrSurfaceOrigin surfaceOrigin)49 std::unique_ptr<SkImageGenerator> GrAHardwareBufferImageGenerator::Make(
50         AHardwareBuffer* graphicBuffer, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace,
51         GrSurfaceOrigin surfaceOrigin) {
52     AHardwareBuffer_Desc bufferDesc;
53     AHardwareBuffer_describe(graphicBuffer, &bufferDesc);
54 
55     SkColorType colorType =
56             GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(bufferDesc.format);
57     SkImageInfo info = SkImageInfo::Make(bufferDesc.width, bufferDesc.height, colorType,
58                                          alphaType, std::move(colorSpace));
59 
60     bool createProtectedImage = 0 != (bufferDesc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
61     return std::unique_ptr<SkImageGenerator>(new GrAHardwareBufferImageGenerator(
62             info, graphicBuffer, alphaType, createProtectedImage,
63             bufferDesc.format, surfaceOrigin));
64 }
65 
GrAHardwareBufferImageGenerator(const SkImageInfo & info,AHardwareBuffer * hardwareBuffer,SkAlphaType alphaType,bool isProtectedContent,uint32_t bufferFormat,GrSurfaceOrigin surfaceOrigin)66 GrAHardwareBufferImageGenerator::GrAHardwareBufferImageGenerator(const SkImageInfo& info,
67         AHardwareBuffer* hardwareBuffer, SkAlphaType alphaType, bool isProtectedContent,
68         uint32_t bufferFormat, GrSurfaceOrigin surfaceOrigin)
69     : INHERITED(info)
70     , fHardwareBuffer(hardwareBuffer)
71     , fBufferFormat(bufferFormat)
72     , fIsProtectedContent(isProtectedContent)
73     , fSurfaceOrigin(surfaceOrigin) {
74     AHardwareBuffer_acquire(fHardwareBuffer);
75 }
76 
~GrAHardwareBufferImageGenerator()77 GrAHardwareBufferImageGenerator::~GrAHardwareBufferImageGenerator() {
78     AHardwareBuffer_release(fHardwareBuffer);
79 }
80 
81 ///////////////////////////////////////////////////////////////////////////////////////////////////
82 
makeView(GrRecordingContext * context)83 GrSurfaceProxyView GrAHardwareBufferImageGenerator::makeView(GrRecordingContext* context) {
84     if (context->abandoned()) {
85         return {};
86     }
87 
88     auto direct = context->asDirectContext();
89     if (!direct) {
90         return {};
91     }
92 
93     GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(direct,
94                                                                              fHardwareBuffer,
95                                                                              fBufferFormat,
96                                                                              false);
97 
98     GrColorType grColorType = SkColorTypeToGrColorType(this->getInfo().colorType());
99 
100     int width = this->getInfo().width();
101     int height = this->getInfo().height();
102 
103     auto proxyProvider = context->priv().proxyProvider();
104 
105     AHardwareBuffer* hardwareBuffer = fHardwareBuffer;
106     AHardwareBuffer_acquire(hardwareBuffer);
107 
108     class AutoAHBRelease {
109     public:
110         AutoAHBRelease(AHardwareBuffer* ahb) : fAhb(ahb) {}
111         // std::function() must be CopyConstructible, but ours should never actually be copied.
112         AutoAHBRelease(const AutoAHBRelease&) { SkASSERT(0); }
113         AutoAHBRelease(AutoAHBRelease&& that) : fAhb(that.fAhb) { that.fAhb = nullptr; }
114         ~AutoAHBRelease() { fAhb ? AHardwareBuffer_release(fAhb) : void(); }
115 
116         AutoAHBRelease& operator=(AutoAHBRelease&& that) {
117             fAhb = std::exchange(that.fAhb, nullptr);
118             return *this;
119         }
120         AutoAHBRelease& operator=(const AutoAHBRelease&) = delete;
121 
122         AHardwareBuffer* get() const { return fAhb; }
123 
124     private:
125         AHardwareBuffer* fAhb;
126     };
127 
128     sk_sp<GrTextureProxy> texProxy = proxyProvider->createLazyProxy(
129             [direct, buffer = AutoAHBRelease(hardwareBuffer)](
130                     GrResourceProvider* resourceProvider,
131                     const GrSurfaceProxy::LazySurfaceDesc& desc)
132                     -> GrSurfaceProxy::LazyCallbackResult {
133                 GrAHardwareBufferUtils::DeleteImageProc deleteImageProc = nullptr;
134                 GrAHardwareBufferUtils::UpdateImageProc updateImageProc = nullptr;
135                 GrAHardwareBufferUtils::TexImageCtx texImageCtx = nullptr;
136 
137                 bool isProtected = desc.fProtected == GrProtected::kYes;
138                 GrBackendTexture backendTex =
139                         GrAHardwareBufferUtils::MakeBackendTexture(direct,
140                                                                    buffer.get(),
141                                                                    desc.fDimensions.width(),
142                                                                    desc.fDimensions.height(),
143                                                                    &deleteImageProc,
144                                                                    &updateImageProc,
145                                                                    &texImageCtx,
146                                                                    isProtected,
147                                                                    desc.fFormat,
148                                                                    false);
149                 if (!backendTex.isValid()) {
150                     return {};
151                 }
152                 SkASSERT(deleteImageProc && texImageCtx);
153 
154                 // We make this texture cacheable to avoid recreating a GrTexture every time this
155                 // is invoked. We know the owning SkImage will send an invalidation message when the
156                 // image is destroyed, so the texture will be removed at that time. Note that the
157                 // proxy will be keyed in GrProxyProvider but that cache just allows extant proxies
158                 // to be reused. It does not retain them. After a flush the proxy will be deleted
159                 // and a subsequent use of the image will recreate a new proxy around the GrTexture
160                 // found in the GrResourceCache.
161                 // This is the last use of GrWrapCacheable::kYes so if we actually cached the proxy
162                 // we could remove wrapped GrGpuResource caching.
163                 sk_sp<GrTexture> tex = resourceProvider->wrapBackendTexture(
164                         backendTex, kBorrow_GrWrapOwnership, GrWrapCacheable::kYes, kRead_GrIOType);
165                 if (!tex) {
166                     deleteImageProc(texImageCtx);
167                     return {};
168                 }
169 
170                 if (deleteImageProc) {
171                     tex->setRelease(deleteImageProc, texImageCtx);
172                 }
173 
174                 return tex;
175             },
176             backendFormat, {width, height}, GrMipmapped::kNo, GrMipmapStatus::kNotAllocated,
177             GrInternalSurfaceFlags::kReadOnly, SkBackingFit::kExact, SkBudgeted::kNo,
178             GrProtected(fIsProtectedContent), GrSurfaceProxy::UseAllocator::kYes);
179 
180     GrSwizzle readSwizzle = context->priv().caps()->getReadSwizzle(backendFormat, grColorType);
181 
182     return GrSurfaceProxyView(std::move(texProxy), fSurfaceOrigin, readSwizzle);
183 }
184 
onGenerateTexture(GrRecordingContext * context,const SkImageInfo & info,const SkIPoint & origin,GrMipmapped mipMapped,GrImageTexGenPolicy texGenPolicy)185 GrSurfaceProxyView GrAHardwareBufferImageGenerator::onGenerateTexture(
186         GrRecordingContext* context,
187         const SkImageInfo& info,
188         const SkIPoint& origin,
189         GrMipmapped mipMapped,
190         GrImageTexGenPolicy texGenPolicy) {
191     GrSurfaceProxyView texProxyView = this->makeView(context);
192     if (!texProxyView.proxy()) {
193         return {};
194     }
195     SkASSERT(texProxyView.asTextureProxy());
196 
197     if (texGenPolicy == GrImageTexGenPolicy::kDraw && origin.isZero() &&
198         info.dimensions() == this->getInfo().dimensions() && mipMapped == GrMipmapped::kNo) {
199         // If the caller wants the full non-MIP mapped texture we're done.
200         return texProxyView;
201     }
202     // Otherwise, make a copy for the requested subset and/or MIP maps.
203     SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, info.width(), info.height());
204 
205     SkBudgeted budgeted = texGenPolicy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted
206                                   ? SkBudgeted::kNo
207                                   : SkBudgeted::kYes;
208 
209     return GrSurfaceProxyView::Copy(context, std::move(texProxyView), mipMapped, subset,
210                                     SkBackingFit::kExact, budgeted);
211 }
212 
onIsValid(GrRecordingContext * context) const213 bool GrAHardwareBufferImageGenerator::onIsValid(GrRecordingContext* context) const {
214     if (nullptr == context) {
215         return false; //CPU backend is not supported, because hardware buffer can be swizzled
216     }
217     return GrBackendApi::kOpenGL == context->backend() ||
218            GrBackendApi::kVulkan == context->backend();
219 }
220 
221 #endif //SK_BUILD_FOR_ANDROID_FRAMEWORK
222