blob: 981337bb496297154cede4465c0182e154b7a7ed [file] [log] [blame]
Stan Iliev7e910df2017-06-02 10:29:21 -04001/*
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#include "SkTypes.h"
8
Derek Sollenberger7a869872017-06-27 15:37:25 -04009
10#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
Stan Iliev7e910df2017-06-02 10:29:21 -040011#define GL_GLEXT_PROTOTYPES
12#define EGL_EGLEXT_PROTOTYPES
13#include "GrAHardwareBufferImageGenerator.h"
14
Derek Sollenberger7a869872017-06-27 15:37:25 -040015#include <android/hardware_buffer.h>
16
Stan Iliev7e910df2017-06-02 10:29:21 -040017#include "GrBackendSurface.h"
18#include "GrContext.h"
19#include "GrContextPriv.h"
Robert Phillipsadbe1322018-01-17 13:35:46 -050020#include "GrProxyProvider.h"
Stan Ilievdbba55d2017-06-28 13:24:41 -040021#include "GrResourceCache.h"
Robert Phillips00018282017-06-15 15:35:16 -040022#include "GrResourceProvider.h"
Robert Phillips847d4c52017-06-13 18:21:44 -040023#include "GrTexture.h"
Robert Phillipsade9f612017-06-16 07:32:43 -040024#include "GrTextureProxy.h"
Stan Ilievdbba55d2017-06-28 13:24:41 -040025#include "SkMessageBus.h"
Greg Danielf1251112018-08-27 09:55:03 -040026#include "gl/GrGLDefines.h"
27#include "gl/GrGLTypes.h"
Stan Iliev7e910df2017-06-02 10:29:21 -040028
29#include <EGL/egl.h>
30#include <EGL/eglext.h>
31#include <GLES/gl.h>
32#include <GLES/glext.h>
33
Stan Ilievc01b5c72018-08-28 10:18:19 -040034#define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
35#define EGL_PROTECTED_CONTENT_EXT 0x32C0
36
37static bool can_import_protected_content_eglimpl() {
38 EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
39 const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
40 size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
41 size_t extsLen = strlen(exts);
42 bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
43 bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1);
44 bool atEnd = (cropExtLen+1) < extsLen
45 && !strcmp(" " PROT_CONTENT_EXT_STR,
46 exts + extsLen - (cropExtLen+1));
47 bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
48 return equal || atStart || atEnd || inMiddle;
49}
50
51static bool can_import_protected_content(GrContext* context) {
52 if (kOpenGL_GrBackend == context->contextPriv().getBackend()) {
53 // Only compute whether the extension is present once the first time this
54 // function is called.
55 static bool hasIt = can_import_protected_content_eglimpl();
56 return hasIt;
57 }
58 return false;
59}
60
Stan Iliev7e910df2017-06-02 10:29:21 -040061std::unique_ptr<SkImageGenerator> GrAHardwareBufferImageGenerator::Make(
62 AHardwareBuffer* graphicBuffer, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace) {
63 AHardwareBuffer_Desc bufferDesc;
64 AHardwareBuffer_describe(graphicBuffer, &bufferDesc);
65 SkColorType colorType;
66 switch (bufferDesc.format) {
67 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
68 colorType = kRGBA_8888_SkColorType;
69 break;
70 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
71 colorType = kRGBA_F16_SkColorType;
72 break;
73 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
74 colorType = kRGB_565_SkColorType;
75 break;
Stan Iliev114b0912018-08-31 14:02:55 -040076 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
77 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
78 colorType = kRGB_888x_SkColorType;
79 break;
80 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
81 colorType = kRGBA_1010102_SkColorType;
82 break;
Stan Iliev7e910df2017-06-02 10:29:21 -040083 default:
Stan Iliev114b0912018-08-31 14:02:55 -040084 // Given that we only use this texture as a source, colorType will not impact how Skia uses
85 // the texture. The only potential affect this is anticipated to have is that for some
86 // format types if we are not bound as an OES texture we may get invalid results for SKP
87 // capture if we read back the texture.
88 colorType = kRGBA_8888_SkColorType;
89 break;
Stan Iliev7e910df2017-06-02 10:29:21 -040090 }
91 SkImageInfo info = SkImageInfo::Make(bufferDesc.width, bufferDesc.height, colorType,
92 alphaType, std::move(colorSpace));
Stan Ilievc01b5c72018-08-28 10:18:19 -040093 bool createProtectedImage = 0 != (bufferDesc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
Stan Iliev7e910df2017-06-02 10:29:21 -040094 return std::unique_ptr<SkImageGenerator>(new GrAHardwareBufferImageGenerator(info, graphicBuffer,
Stan Iliev114b0912018-08-31 14:02:55 -040095 alphaType, createProtectedImage, bufferDesc.format));
Stan Iliev7e910df2017-06-02 10:29:21 -040096}
97
98GrAHardwareBufferImageGenerator::GrAHardwareBufferImageGenerator(const SkImageInfo& info,
Stan Iliev114b0912018-08-31 14:02:55 -040099 AHardwareBuffer* hardwareBuffer, SkAlphaType alphaType, bool isProtectedContent,
100 uint32_t bufferFormat)
Stan Iliev7e910df2017-06-02 10:29:21 -0400101 : INHERITED(info)
Stan Ilievc01b5c72018-08-28 10:18:19 -0400102 , fHardwareBuffer(hardwareBuffer)
Stan Iliev114b0912018-08-31 14:02:55 -0400103 , fBufferFormat(bufferFormat)
Stan Ilievc01b5c72018-08-28 10:18:19 -0400104 , fIsProtectedContent(isProtectedContent) {
Greg Danielf1251112018-08-27 09:55:03 -0400105 AHardwareBuffer_acquire(fHardwareBuffer);
106}
107
108void GrAHardwareBufferImageGenerator::releaseTextureRef() {
109 // We must release our ref on the proxy before we send the free message to the actual texture so
110 // that we make sure the last ref (if it is owned by this class) is released on the owning
111 // context.
112 fCachedProxy.reset();
113 if (fOwnedTexture) {
114 SkASSERT(fOwningContextID != SK_InvalidGenID);
115 // Notify the original cache that it can free the last ref, so it happens on the correct
116 // thread.
117 GrGpuResourceFreedMessage msg { fOwnedTexture, fOwningContextID };
118 SkMessageBus<GrGpuResourceFreedMessage>::Post(msg);
119 fOwnedTexture = nullptr;
120 fOwningContextID = SK_InvalidGenID;
121 }
Stan Iliev7e910df2017-06-02 10:29:21 -0400122}
123
124GrAHardwareBufferImageGenerator::~GrAHardwareBufferImageGenerator() {
Greg Danielf1251112018-08-27 09:55:03 -0400125 this->releaseTextureRef();
126 AHardwareBuffer_release(fHardwareBuffer);
Stan Iliev7e910df2017-06-02 10:29:21 -0400127}
128
Stan Iliev7e910df2017-06-02 10:29:21 -0400129///////////////////////////////////////////////////////////////////////////////////////////////////
130
Stan Iliev7e910df2017-06-02 10:29:21 -0400131sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::onGenerateTexture(
Brian Osmanc87cfb62018-07-11 09:08:46 -0400132 GrContext* context, const SkImageInfo& info, const SkIPoint& origin, bool willNeedMipMaps) {
Greg Danielf1251112018-08-27 09:55:03 -0400133 this->makeProxy(context);
134 if (!fCachedProxy) {
Stan Ilievdbba55d2017-06-28 13:24:41 -0400135 return nullptr;
136 }
Stan Iliev7e910df2017-06-02 10:29:21 -0400137
Greg Daniel65c7f662017-10-30 13:39:09 -0400138 bool makingASubset = true;
Stan Ilievdbba55d2017-06-28 13:24:41 -0400139 if (0 == origin.fX && 0 == origin.fY &&
Greg Daniel9af948d2018-08-27 09:53:51 -0400140 info.width() == this->getInfo().width() && info.height() == this->getInfo().height()) {
Greg Daniel65c7f662017-10-30 13:39:09 -0400141 makingASubset = false;
Greg Danielf1251112018-08-27 09:55:03 -0400142 if (!willNeedMipMaps || GrMipMapped::kYes == fCachedProxy->mipMapped()) {
Greg Daniel65c7f662017-10-30 13:39:09 -0400143 // If the caller wants the full texture and we have the correct mip support, we're done
Greg Danielf1251112018-08-27 09:55:03 -0400144 return fCachedProxy;
Greg Daniel65c7f662017-10-30 13:39:09 -0400145 }
Stan Ilievdbba55d2017-06-28 13:24:41 -0400146 }
Greg Daniel65c7f662017-10-30 13:39:09 -0400147 // Otherwise, make a copy for the requested subset or for mip maps.
148 SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, info.width(), info.height());
149
150 GrMipMapped mipMapped = willNeedMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo;
151
Greg Danielf1251112018-08-27 09:55:03 -0400152 sk_sp<GrTextureProxy> texProxy = GrSurfaceProxy::Copy(context, fCachedProxy.get(), mipMapped,
Greg Daniel65c7f662017-10-30 13:39:09 -0400153 subset, SkBudgeted::kYes);
154 if (!makingASubset && texProxy) {
155 // We are in this case if we wanted the full texture, but we will be mip mapping the
156 // texture. Therefore we want to update the cached texture so that we point to the
157 // mipped version instead of the old one.
158 SkASSERT(willNeedMipMaps);
159 SkASSERT(GrMipMapped::kYes == texProxy->mipMapped());
160
161 // The only way we should get into here is if we just made a new texture in makeProxy or
162 // we found a cached texture in the same context. Thus the current and cached contexts
163 // should match.
164 SkASSERT(context->uniqueID() == fOwningContextID);
165
Greg Danielf1251112018-08-27 09:55:03 -0400166 // Since we no longer will be caching the and reusing the texture that actually wraps the
167 // hardware buffer, we can release our refs on it.
168 this->releaseTextureRef();
Greg Daniel65c7f662017-10-30 13:39:09 -0400169
Greg Danielf1251112018-08-27 09:55:03 -0400170 fCachedProxy = texProxy;
Greg Daniel65c7f662017-10-30 13:39:09 -0400171 }
172 return texProxy;
Stan Ilievdbba55d2017-06-28 13:24:41 -0400173}
Stan Ilievdbba55d2017-06-28 13:24:41 -0400174
Greg Daniel9af948d2018-08-27 09:53:51 -0400175class BufferCleanupHelper {
176public:
177 BufferCleanupHelper(EGLImageKHR image, EGLDisplay display)
178 : fImage(image)
179 , fDisplay(display) { }
180 ~BufferCleanupHelper() {
Greg Danielf1251112018-08-27 09:55:03 -0400181 // eglDestroyImageKHR will remove a ref from the AHardwareBuffer
Greg Daniel9af948d2018-08-27 09:53:51 -0400182 eglDestroyImageKHR(fDisplay, fImage);
183 }
184private:
185 EGLImageKHR fImage;
186 EGLDisplay fDisplay;
187};
188
189
190void GrAHardwareBufferImageGenerator::DeleteEGLImage(void* context) {
191 BufferCleanupHelper* cleanupHelper = static_cast<BufferCleanupHelper*>(context);
192 delete cleanupHelper;
193}
194
195static GrBackendTexture make_gl_backend_texture(
196 GrContext* context, AHardwareBuffer* hardwareBuffer,
Greg Danielf1251112018-08-27 09:55:03 -0400197 int width, int height, GrPixelConfig config,
Greg Daniel9af948d2018-08-27 09:53:51 -0400198 GrAHardwareBufferImageGenerator::DeleteImageProc* deleteProc,
Stan Ilievc01b5c72018-08-28 10:18:19 -0400199 GrAHardwareBufferImageGenerator::DeleteImageCtx* deleteCtx,
Stan Iliev114b0912018-08-31 14:02:55 -0400200 bool isProtectedContent,
201 const GrBackendFormat& backendFormat) {
Greg Daniel9af948d2018-08-27 09:53:51 -0400202 while (GL_NO_ERROR != glGetError()) {} //clear GL errors
203
Stan Ilievc01b5c72018-08-28 10:18:19 -0400204 EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer);
Greg Daniel9af948d2018-08-27 09:53:51 -0400205 EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
Stan Ilievc01b5c72018-08-28 10:18:19 -0400206 isProtectedContent ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
207 isProtectedContent ? EGL_TRUE : EGL_NONE,
Greg Daniel9af948d2018-08-27 09:53:51 -0400208 EGL_NONE };
209 EGLDisplay display = eglGetCurrentDisplay();
Greg Danielf1251112018-08-27 09:55:03 -0400210 // eglCreateImageKHR will add a ref to the AHardwareBuffer
Greg Daniel9af948d2018-08-27 09:53:51 -0400211 EGLImageKHR image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
212 clientBuffer, attribs);
213 if (EGL_NO_IMAGE_KHR == image) {
214 SkDebugf("Could not create EGL image, err = (%#x)", (int) eglGetError() );
215 return GrBackendTexture();
216 }
217
218 GrGLuint texID;
219 glGenTextures(1, &texID);
220 if (!texID) {
221 eglDestroyImageKHR(display, image);
222 return GrBackendTexture();
223 }
224 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texID);
225 GLenum status = GL_NO_ERROR;
226 if ((status = glGetError()) != GL_NO_ERROR) {
227 SkDebugf("glBindTexture failed (%#x)", (int) status);
228 glDeleteTextures(1, &texID);
229 eglDestroyImageKHR(display, image);
230 return GrBackendTexture();
231 }
232 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
233 if ((status = glGetError()) != GL_NO_ERROR) {
234 SkDebugf("glEGLImageTargetTexture2DOES failed (%#x)", (int) status);
235 glDeleteTextures(1, &texID);
236 eglDestroyImageKHR(display, image);
237 return GrBackendTexture();
238 }
239 context->resetContext(kTextureBinding_GrGLBackendState);
240
241 GrGLTextureInfo textureInfo;
Greg Daniel9af948d2018-08-27 09:53:51 -0400242 textureInfo.fID = texID;
Stan Iliev114b0912018-08-31 14:02:55 -0400243 SkASSERT(backendFormat.isValid());
244 textureInfo.fTarget = *backendFormat.getGLTarget();
245 textureInfo.fFormat = *backendFormat.getGLFormat();
Greg Daniel9af948d2018-08-27 09:53:51 -0400246
247 *deleteProc = GrAHardwareBufferImageGenerator::DeleteEGLImage;
248 *deleteCtx = new BufferCleanupHelper(image, display);
249
250 return GrBackendTexture(width, height, GrMipMapped::kNo, textureInfo);
251}
252
253static GrBackendTexture make_backend_texture(
254 GrContext* context, AHardwareBuffer* hardwareBuffer,
Greg Danielf1251112018-08-27 09:55:03 -0400255 int width, int height, GrPixelConfig config,
Greg Daniel9af948d2018-08-27 09:53:51 -0400256 GrAHardwareBufferImageGenerator::DeleteImageProc* deleteProc,
Stan Ilievc01b5c72018-08-28 10:18:19 -0400257 GrAHardwareBufferImageGenerator::DeleteImageCtx* deleteCtx,
Stan Iliev114b0912018-08-31 14:02:55 -0400258 bool isProtectedContent,
259 const GrBackendFormat& backendFormat) {
Greg Daniel9af948d2018-08-27 09:53:51 -0400260 if (context->abandoned() || kOpenGL_GrBackend != context->contextPriv().getBackend()) {
261 // Check if GrContext is not abandoned and the backend is GL.
262 return GrBackendTexture();
263 }
Stan Ilievc01b5c72018-08-28 10:18:19 -0400264 bool createProtectedImage = isProtectedContent && can_import_protected_content(context);
Greg Danielf1251112018-08-27 09:55:03 -0400265 return make_gl_backend_texture(context, hardwareBuffer, width, height, config, deleteProc,
Stan Iliev114b0912018-08-31 14:02:55 -0400266 deleteCtx, createProtectedImage, backendFormat);
Greg Daniel9af948d2018-08-27 09:53:51 -0400267}
268
269static void free_backend_texture(GrBackendTexture* backendTexture) {
270 SkASSERT(backendTexture && backendTexture->isValid());
271
272 switch (backendTexture->backend()) {
273 case kOpenGL_GrBackend: {
274 GrGLTextureInfo texInfo;
275 SkAssertResult(backendTexture->getGLTextureInfo(&texInfo));
276 glDeleteTextures(1, &texInfo.fID);
277 return;
278 }
279 case kVulkan_GrBackend: // fall through
280 default:
281 return;
282 }
283}
284
Stan Iliev114b0912018-08-31 14:02:55 -0400285GrBackendFormat get_backend_format(GrBackend backend, uint32_t bufferFormat) {
286 if (backend == kOpenGL_GrBackend) {
287 switch (bufferFormat) {
288 //TODO: find out if we can detect, which graphic buffers support GR_GL_TEXTURE_2D
289 case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
290 return GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_EXTERNAL);
291 case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
292 return GrBackendFormat::MakeGL(GR_GL_RGBA16F, GR_GL_TEXTURE_EXTERNAL);
293 case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
294 return GrBackendFormat::MakeGL(GR_GL_RGB565, GR_GL_TEXTURE_EXTERNAL);
295 case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
296 return GrBackendFormat::MakeGL(GR_GL_RGB10_A2, GR_GL_TEXTURE_EXTERNAL);
297 case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
298 case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
299 return GrBackendFormat::MakeGL(GR_GL_RGB8, GR_GL_TEXTURE_EXTERNAL);
300 default:
301 return GrBackendFormat::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_EXTERNAL);
302 }
303 }
304 return GrBackendFormat();
305}
306
Greg Danielf1251112018-08-27 09:55:03 -0400307void GrAHardwareBufferImageGenerator::makeProxy(GrContext* context) {
Khushalc421ca12018-06-26 14:38:34 -0700308 if (context->abandoned() || kOpenGL_GrBackend != context->contextPriv().getBackend()) {
Stan Iliev7e910df2017-06-02 10:29:21 -0400309 // Check if GrContext is not abandoned and the backend is GL.
Greg Danielf1251112018-08-27 09:55:03 -0400310 return;
Stan Iliev7e910df2017-06-02 10:29:21 -0400311 }
312
Greg Danielf1251112018-08-27 09:55:03 -0400313 if (SK_InvalidGenID != fOwningContextID) {
314 SkASSERT(fCachedProxy);
315 if (context->uniqueID() != fOwningContextID) {
316 this->releaseTextureRef();
317 } else {
318 return;
319 }
Stan Ilievdbba55d2017-06-28 13:24:41 -0400320 }
Greg Danielf1251112018-08-27 09:55:03 -0400321 SkASSERT(!fCachedProxy);
322
323 fOwningContextID = context->uniqueID();
Stan Ilievdbba55d2017-06-28 13:24:41 -0400324
Stan Iliev7e910df2017-06-02 10:29:21 -0400325 GrPixelConfig pixelConfig;
Stan Iliev114b0912018-08-31 14:02:55 -0400326 GrBackendFormat backendFormat = get_backend_format(context->contextPriv().getBackend(),
327 fBufferFormat);
328 if (!context->contextPriv().caps()->getConfigFromBackendFormat(
329 backendFormat, this->getInfo().colorType(), &pixelConfig)) {
330 return;
Stan Iliev7e910df2017-06-02 10:29:21 -0400331 }
332
Greg Danielf1251112018-08-27 09:55:03 -0400333 int width = this->getInfo().width();
334 int height = this->getInfo().height();
Greg Daniel9af948d2018-08-27 09:53:51 -0400335
Greg Danielf1251112018-08-27 09:55:03 -0400336 GrSurfaceDesc desc;
337 desc.fWidth = width;
338 desc.fHeight = height;
339 desc.fConfig = pixelConfig;
Greg Daniel9af948d2018-08-27 09:53:51 -0400340
Greg Danielf1251112018-08-27 09:55:03 -0400341 GrTextureType textureType = GrTextureType::k2D;
342 if (context->contextPriv().getBackend() == kOpenGL_GrBackend) {
343 textureType = GrTextureType::kExternal;
Stan Iliev7e910df2017-06-02 10:29:21 -0400344 }
Greg Daniel6a0176b2018-01-30 09:28:44 -0500345
Greg Danielf1251112018-08-27 09:55:03 -0400346 auto proxyProvider = context->contextPriv().proxyProvider();
347
348 AHardwareBuffer* hardwareBuffer = fHardwareBuffer;
349 AHardwareBuffer_acquire(hardwareBuffer);
350
351 GrTexture** ownedTexturePtr = &fOwnedTexture;
Stan Ilievc01b5c72018-08-28 10:18:19 -0400352 const bool isProtectedContent = fIsProtectedContent;
Greg Danielf1251112018-08-27 09:55:03 -0400353
354 fCachedProxy = proxyProvider->createLazyProxy(
Stan Ilievc01b5c72018-08-28 10:18:19 -0400355 [context, hardwareBuffer, width, height, pixelConfig, ownedTexturePtr,
Stan Iliev114b0912018-08-31 14:02:55 -0400356 isProtectedContent, backendFormat]
Greg Danielf1251112018-08-27 09:55:03 -0400357 (GrResourceProvider* resourceProvider) {
358 if (!resourceProvider) {
359 AHardwareBuffer_release(hardwareBuffer);
360 return sk_sp<GrTexture>();
361 }
362
363 SkASSERT(!*ownedTexturePtr);
364
365 DeleteImageProc deleteImageProc = nullptr;
366 DeleteImageCtx deleteImageCtx = nullptr;
367
368 GrBackendTexture backendTex = make_backend_texture(context, hardwareBuffer,
369 width, height, pixelConfig,
370 &deleteImageProc,
Stan Ilievc01b5c72018-08-28 10:18:19 -0400371 &deleteImageCtx,
Stan Iliev114b0912018-08-31 14:02:55 -0400372 isProtectedContent,
373 backendFormat);
Greg Danielf1251112018-08-27 09:55:03 -0400374 if (!backendTex.isValid()) {
375 return sk_sp<GrTexture>();
376 }
377 SkASSERT(deleteImageProc && deleteImageCtx);
378
379 backendTex.fConfig = pixelConfig;
380 sk_sp<GrTexture> tex = resourceProvider->wrapBackendTexture(
381 backendTex, kAdopt_GrWrapOwnership);
382 if (!tex) {
383 free_backend_texture(&backendTex);
384 deleteImageProc(deleteImageCtx);
385 return sk_sp<GrTexture>();
386 }
387
388 sk_sp<GrReleaseProcHelper> releaseProcHelper(
Greg Daniel9af948d2018-08-27 09:53:51 -0400389 new GrReleaseProcHelper(deleteImageProc, deleteImageCtx));
Greg Danielf1251112018-08-27 09:55:03 -0400390 tex->setRelease(releaseProcHelper);
Stan Iliev7e910df2017-06-02 10:29:21 -0400391
Greg Danielf1251112018-08-27 09:55:03 -0400392 *ownedTexturePtr = tex.get();
Stan Iliev7e910df2017-06-02 10:29:21 -0400393
Greg Danielf1251112018-08-27 09:55:03 -0400394 // Attach our texture to this context's resource cache. This ensures that deletion
395 // will happen in the correct thread/context. This adds the only ref to the texture
396 // that will persist from this point. To trigger GrTexture deletion a message is
397 // sent by generator dtor or by makeProxy when it is invoked with a different
398 // context.
399 context->contextPriv().getResourceCache()->insertCrossContextGpuResource(tex.get());
400 return tex;
401 },
402 desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, textureType, SkBackingFit::kExact,
403 SkBudgeted::kNo);
404
405
406 if (!fCachedProxy) {
407 AHardwareBuffer_release(hardwareBuffer);
408 return;
409 }
Stan Iliev7e910df2017-06-02 10:29:21 -0400410}
Stan Iliev7e910df2017-06-02 10:29:21 -0400411
412bool GrAHardwareBufferImageGenerator::onIsValid(GrContext* context) const {
413 if (nullptr == context) {
414 return false; //CPU backend is not supported, because hardware buffer can be swizzled
415 }
416 // TODO: add Vulkan support
417 return kOpenGL_GrBackend == context->contextPriv().getBackend();
418}
419
420#endif //SK_BUILD_FOR_ANDROID_FRAMEWORK