blob: d42b4918ff870d658f41a31f5ed3fa3320d0d462 [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 */
Stan Iliev7e910df2017-06-02 10:29:21 -04007
Greg Daniel54bfb182018-11-20 17:12:36 -05008#include "SkTypes.h"
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
Greg Daniel54bfb182018-11-20 17:12:36 -050013
Greg Daniel54bfb182018-11-20 17:12:36 -050014
Stan Iliev7e910df2017-06-02 10:29:21 -040015#include "GrAHardwareBufferImageGenerator.h"
16
Derek Sollenberger7a869872017-06-27 15:37:25 -040017#include <android/hardware_buffer.h>
18
Greg Daniel173464d2019-02-06 15:30:34 -050019#include "GrAHardwareBufferUtils.h"
Stan Iliev7e910df2017-06-02 10:29:21 -040020#include "GrBackendSurface.h"
21#include "GrContext.h"
22#include "GrContextPriv.h"
Robert Phillipsadbe1322018-01-17 13:35:46 -050023#include "GrProxyProvider.h"
Stan Ilievdbba55d2017-06-28 13:24:41 -040024#include "GrResourceCache.h"
Robert Phillips00018282017-06-15 15:35:16 -040025#include "GrResourceProvider.h"
Greg Daniel637c06a2018-09-12 09:44:25 -040026#include "GrResourceProviderPriv.h"
Robert Phillips847d4c52017-06-13 18:21:44 -040027#include "GrTexture.h"
Robert Phillipsade9f612017-06-16 07:32:43 -040028#include "GrTextureProxy.h"
Stan Ilievdbba55d2017-06-28 13:24:41 -040029#include "SkMessageBus.h"
Greg Danielf1251112018-08-27 09:55:03 -040030#include "gl/GrGLDefines.h"
31#include "gl/GrGLTypes.h"
Stan Iliev7e910df2017-06-02 10:29:21 -040032
33#include <EGL/egl.h>
34#include <EGL/eglext.h>
35#include <GLES/gl.h>
36#include <GLES/glext.h>
37
Greg Daniel637c06a2018-09-12 09:44:25 -040038#ifdef SK_VULKAN
39#include "vk/GrVkExtensions.h"
40#include "vk/GrVkGpu.h"
41#endif
42
Stan Ilievc01b5c72018-08-28 10:18:19 -040043#define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
44#define EGL_PROTECTED_CONTENT_EXT 0x32C0
45
Stan Iliev7e910df2017-06-02 10:29:21 -040046std::unique_ptr<SkImageGenerator> GrAHardwareBufferImageGenerator::Make(
Stan Iliev505dd572018-09-13 14:20:03 -040047 AHardwareBuffer* graphicBuffer, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace,
48 GrSurfaceOrigin surfaceOrigin) {
Stan Iliev7e910df2017-06-02 10:29:21 -040049 AHardwareBuffer_Desc bufferDesc;
50 AHardwareBuffer_describe(graphicBuffer, &bufferDesc);
Greg Daniel173464d2019-02-06 15:30:34 -050051
52 SkColorType colorType =
53 GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(bufferDesc.format);
Stan Iliev7e910df2017-06-02 10:29:21 -040054 SkImageInfo info = SkImageInfo::Make(bufferDesc.width, bufferDesc.height, colorType,
55 alphaType, std::move(colorSpace));
Greg Daniel173464d2019-02-06 15:30:34 -050056
Stan Ilievc01b5c72018-08-28 10:18:19 -040057 bool createProtectedImage = 0 != (bufferDesc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
Stan Iliev505dd572018-09-13 14:20:03 -040058 return std::unique_ptr<SkImageGenerator>(new GrAHardwareBufferImageGenerator(
59 info, graphicBuffer, alphaType, createProtectedImage,
60 bufferDesc.format, surfaceOrigin));
Stan Iliev7e910df2017-06-02 10:29:21 -040061}
62
63GrAHardwareBufferImageGenerator::GrAHardwareBufferImageGenerator(const SkImageInfo& info,
Stan Iliev114b0912018-08-31 14:02:55 -040064 AHardwareBuffer* hardwareBuffer, SkAlphaType alphaType, bool isProtectedContent,
Stan Iliev505dd572018-09-13 14:20:03 -040065 uint32_t bufferFormat, GrSurfaceOrigin surfaceOrigin)
Stan Iliev7e910df2017-06-02 10:29:21 -040066 : INHERITED(info)
Stan Ilievc01b5c72018-08-28 10:18:19 -040067 , fHardwareBuffer(hardwareBuffer)
Stan Iliev114b0912018-08-31 14:02:55 -040068 , fBufferFormat(bufferFormat)
Stan Iliev505dd572018-09-13 14:20:03 -040069 , fIsProtectedContent(isProtectedContent)
70 , fSurfaceOrigin(surfaceOrigin) {
Greg Danielf1251112018-08-27 09:55:03 -040071 AHardwareBuffer_acquire(fHardwareBuffer);
72}
73
Stan Iliev7e910df2017-06-02 10:29:21 -040074GrAHardwareBufferImageGenerator::~GrAHardwareBufferImageGenerator() {
Greg Danielf1251112018-08-27 09:55:03 -040075 AHardwareBuffer_release(fHardwareBuffer);
Stan Iliev7e910df2017-06-02 10:29:21 -040076}
77
Stan Iliev7e910df2017-06-02 10:29:21 -040078///////////////////////////////////////////////////////////////////////////////////////////////////
79
Greg Daniel3860cfd12018-09-07 09:13:54 -040080sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::makeProxy(GrContext* context) {
Greg Daniel637c06a2018-09-12 09:44:25 -040081 if (context->abandoned()) {
Greg Daniel3860cfd12018-09-07 09:13:54 -040082 return nullptr;
Stan Iliev7e910df2017-06-02 10:29:21 -040083 }
84
Greg Daniel173464d2019-02-06 15:30:34 -050085 GrBackendFormat backendFormat = GrAHardwareBufferUtils::GetBackendFormat(context,
86 fHardwareBuffer,
87 fBufferFormat,
88 false);
89
Robert Phillips9da87e02019-02-04 13:26:26 -050090 GrPixelConfig pixelConfig = context->priv().caps()->getConfigFromBackendFormat(
Brian Salomonf391d0f2018-12-14 09:18:50 -050091 backendFormat, this->getInfo().colorType());
92
93 if (pixelConfig == kUnknown_GrPixelConfig) {
Greg Daniel3860cfd12018-09-07 09:13:54 -040094 return nullptr;
Stan Iliev7e910df2017-06-02 10:29:21 -040095 }
96
Greg Danielf1251112018-08-27 09:55:03 -040097 int width = this->getInfo().width();
98 int height = this->getInfo().height();
Greg Daniel9af948d2018-08-27 09:53:51 -040099
Greg Danielf1251112018-08-27 09:55:03 -0400100 GrSurfaceDesc desc;
101 desc.fWidth = width;
102 desc.fHeight = height;
103 desc.fConfig = pixelConfig;
Greg Daniel9af948d2018-08-27 09:53:51 -0400104
Greg Danielf1251112018-08-27 09:55:03 -0400105 GrTextureType textureType = GrTextureType::k2D;
Robert Phillips4217ea72019-01-30 13:08:28 -0500106 if (context->backend() == GrBackendApi::kOpenGL) {
Greg Danielf1251112018-08-27 09:55:03 -0400107 textureType = GrTextureType::kExternal;
Robert Phillips4217ea72019-01-30 13:08:28 -0500108 } else if (context->backend() == GrBackendApi::kVulkan) {
Greg Daniel14c55c22018-12-04 11:25:03 -0500109 const VkFormat* format = backendFormat.getVkFormat();
110 SkASSERT(format);
111 if (*format == VK_FORMAT_UNDEFINED) {
112 textureType = GrTextureType::kExternal;
113 }
Stan Iliev7e910df2017-06-02 10:29:21 -0400114 }
Greg Daniel6a0176b2018-01-30 09:28:44 -0500115
Robert Phillips9da87e02019-02-04 13:26:26 -0500116 auto proxyProvider = context->priv().proxyProvider();
Greg Danielf1251112018-08-27 09:55:03 -0400117
118 AHardwareBuffer* hardwareBuffer = fHardwareBuffer;
119 AHardwareBuffer_acquire(hardwareBuffer);
120
Stan Ilievc01b5c72018-08-28 10:18:19 -0400121 const bool isProtectedContent = fIsProtectedContent;
Greg Danielf1251112018-08-27 09:55:03 -0400122
Greg Daniel3860cfd12018-09-07 09:13:54 -0400123 sk_sp<GrTextureProxy> texProxy = proxyProvider->createLazyProxy(
Brian Salomonc67c31c2018-12-06 10:00:03 -0500124 [context, hardwareBuffer, width, height, pixelConfig, isProtectedContent,
125 backendFormat](GrResourceProvider* resourceProvider) {
Greg Danielf1251112018-08-27 09:55:03 -0400126 if (!resourceProvider) {
127 AHardwareBuffer_release(hardwareBuffer);
128 return sk_sp<GrTexture>();
129 }
130
Greg Daniel173464d2019-02-06 15:30:34 -0500131 GrAHardwareBufferUtils::DeleteImageProc deleteImageProc = nullptr;
132 GrAHardwareBufferUtils::DeleteImageCtx deleteImageCtx = nullptr;
Greg Danielf1251112018-08-27 09:55:03 -0400133
Greg Daniel173464d2019-02-06 15:30:34 -0500134 GrBackendTexture backendTex =
135 GrAHardwareBufferUtils::MakeBackendTexture(context, hardwareBuffer,
136 width, height,
Greg Danielf1251112018-08-27 09:55:03 -0400137 &deleteImageProc,
Stan Ilievc01b5c72018-08-28 10:18:19 -0400138 &deleteImageCtx,
Stan Iliev114b0912018-08-31 14:02:55 -0400139 isProtectedContent,
Greg Daniel173464d2019-02-06 15:30:34 -0500140 backendFormat,
141 false);
Greg Danielf1251112018-08-27 09:55:03 -0400142 if (!backendTex.isValid()) {
143 return sk_sp<GrTexture>();
144 }
145 SkASSERT(deleteImageProc && deleteImageCtx);
146
147 backendTex.fConfig = pixelConfig;
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500148 // We make this texture cacheable to avoid recreating a GrTexture every time this
149 // is invoked. We know the owning SkIamge will send an invalidation message when the
150 // image is destroyed, so the texture will be removed at that time.
Brian Salomonc67c31c2018-12-06 10:00:03 -0500151 sk_sp<GrTexture> tex = resourceProvider->wrapBackendTexture(
Brian Salomonaa6ca0a2019-01-24 16:03:07 -0500152 backendTex, kBorrow_GrWrapOwnership, GrWrapCacheable::kYes, kRead_GrIOType);
Greg Danielf1251112018-08-27 09:55:03 -0400153 if (!tex) {
Greg Danielf1251112018-08-27 09:55:03 -0400154 deleteImageProc(deleteImageCtx);
155 return sk_sp<GrTexture>();
156 }
157
Greg Daniel637c06a2018-09-12 09:44:25 -0400158 if (deleteImageProc) {
159 sk_sp<GrReleaseProcHelper> releaseProcHelper(
160 new GrReleaseProcHelper(deleteImageProc, deleteImageCtx));
161 tex->setRelease(releaseProcHelper);
162 }
Stan Iliev7e910df2017-06-02 10:29:21 -0400163
Greg Danielf1251112018-08-27 09:55:03 -0400164 return tex;
165 },
Brian Salomonc67c31c2018-12-06 10:00:03 -0500166 backendFormat, desc, fSurfaceOrigin, GrMipMapped::kNo,
167 GrInternalSurfaceFlags::kReadOnly, SkBackingFit::kExact, SkBudgeted::kNo);
Greg Danielf1251112018-08-27 09:55:03 -0400168
Greg Daniel3860cfd12018-09-07 09:13:54 -0400169 if (!texProxy) {
Greg Danielf1251112018-08-27 09:55:03 -0400170 AHardwareBuffer_release(hardwareBuffer);
Greg Danielf1251112018-08-27 09:55:03 -0400171 }
Greg Daniel3860cfd12018-09-07 09:13:54 -0400172 return texProxy;
173}
174
175sk_sp<GrTextureProxy> GrAHardwareBufferImageGenerator::onGenerateTexture(
176 GrContext* context, const SkImageInfo& info, const SkIPoint& origin, bool willNeedMipMaps) {
177 sk_sp<GrTextureProxy> texProxy = this->makeProxy(context);
178 if (!texProxy) {
179 return nullptr;
180 }
181
182 if (0 == origin.fX && 0 == origin.fY &&
183 info.width() == this->getInfo().width() && info.height() == this->getInfo().height()) {
184 // If the caller wants the full texture we're done. The caller will handle making a copy for
185 // mip maps if that is required.
186 return texProxy;
187 }
188 // Otherwise, make a copy for the requested subset.
189 SkIRect subset = SkIRect::MakeXYWH(origin.fX, origin.fY, info.width(), info.height());
190
191 GrMipMapped mipMapped = willNeedMipMaps ? GrMipMapped::kYes : GrMipMapped::kNo;
192
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500193 return GrSurfaceProxy::Copy(context, texProxy.get(), mipMapped, subset, SkBackingFit::kExact,
194 SkBudgeted::kYes);
Stan Iliev7e910df2017-06-02 10:29:21 -0400195}
Stan Iliev7e910df2017-06-02 10:29:21 -0400196
197bool GrAHardwareBufferImageGenerator::onIsValid(GrContext* context) const {
198 if (nullptr == context) {
199 return false; //CPU backend is not supported, because hardware buffer can be swizzled
200 }
Robert Phillips4217ea72019-01-30 13:08:28 -0500201 return GrBackendApi::kOpenGL == context->backend() ||
202 GrBackendApi::kVulkan == context->backend();
Stan Iliev7e910df2017-06-02 10:29:21 -0400203}
204
205#endif //SK_BUILD_FOR_ANDROID_FRAMEWORK