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 49std::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 66GrAHardwareBufferImageGenerator::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 77GrAHardwareBufferImageGenerator::~GrAHardwareBufferImageGenerator() { 78 AHardwareBuffer_release(fHardwareBuffer); 79} 80 81/////////////////////////////////////////////////////////////////////////////////////////////////// 82 83GrSurfaceProxyView 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 185GrSurfaceProxyView 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 213bool 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