Add support for hardware buffers with protected content

Use EGL_EXT_protected_content extension if present to render
AHardwareBuffer with AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT.

Bug: skia:
Change-Id: I1a5fa4cdc8f432b89ae9ef889175b50a25b846e0
Reviewed-on: https://skia-review.googlesource.com/149803
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Stan Iliev <stani@google.com>
diff --git a/src/gpu/GrAHardwareBufferImageGenerator.cpp b/src/gpu/GrAHardwareBufferImageGenerator.cpp
index 9d7c27b..332f8c5 100644
--- a/src/gpu/GrAHardwareBufferImageGenerator.cpp
+++ b/src/gpu/GrAHardwareBufferImageGenerator.cpp
@@ -31,6 +31,33 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
+#define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
+#define EGL_PROTECTED_CONTENT_EXT 0x32C0
+
+static bool can_import_protected_content_eglimpl() {
+    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
+    size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
+    size_t extsLen = strlen(exts);
+    bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
+    bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1);
+    bool atEnd = (cropExtLen+1) < extsLen
+                  && !strcmp(" " PROT_CONTENT_EXT_STR,
+                  exts + extsLen - (cropExtLen+1));
+    bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
+    return equal || atStart || atEnd || inMiddle;
+}
+
+static bool can_import_protected_content(GrContext* context) {
+    if (kOpenGL_GrBackend == context->contextPriv().getBackend()) {
+        // Only compute whether the extension is present once the first time this
+        // function is called.
+        static bool hasIt = can_import_protected_content_eglimpl();
+        return hasIt;
+    }
+    return false;
+}
+
 std::unique_ptr<SkImageGenerator> GrAHardwareBufferImageGenerator::Make(
         AHardwareBuffer* graphicBuffer, SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace) {
     AHardwareBuffer_Desc bufferDesc;
@@ -51,14 +78,16 @@
     }
     SkImageInfo info = SkImageInfo::Make(bufferDesc.width, bufferDesc.height, colorType,
                                          alphaType, std::move(colorSpace));
+    bool createProtectedImage = 0 != (bufferDesc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
     return std::unique_ptr<SkImageGenerator>(new GrAHardwareBufferImageGenerator(info, graphicBuffer,
-            alphaType));
+            alphaType, createProtectedImage));
 }
 
 GrAHardwareBufferImageGenerator::GrAHardwareBufferImageGenerator(const SkImageInfo& info,
-        AHardwareBuffer* hardwareBuffer, SkAlphaType alphaType)
+        AHardwareBuffer* hardwareBuffer, SkAlphaType alphaType, bool isProtectedContent)
     : INHERITED(info)
-    , fHardwareBuffer(hardwareBuffer) {
+    , fHardwareBuffer(hardwareBuffer)
+    , fIsProtectedContent(isProtectedContent) {
     AHardwareBuffer_acquire(fHardwareBuffer);
 }
 
@@ -153,11 +182,14 @@
         GrContext* context, AHardwareBuffer* hardwareBuffer,
         int width, int height, GrPixelConfig config,
         GrAHardwareBufferImageGenerator::DeleteImageProc* deleteProc,
-        GrAHardwareBufferImageGenerator::DeleteImageCtx* deleteCtx) {
+        GrAHardwareBufferImageGenerator::DeleteImageCtx* deleteCtx,
+        bool isProtectedContent) {
     while (GL_NO_ERROR != glGetError()) {} //clear GL errors
 
-    EGLClientBuffer  clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer);
+    EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(hardwareBuffer);
     EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
+                         isProtectedContent ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+                         isProtectedContent ? EGL_TRUE : EGL_NONE,
                          EGL_NONE };
     EGLDisplay display = eglGetCurrentDisplay();
     // eglCreateImageKHR will add a ref to the AHardwareBuffer
@@ -218,13 +250,15 @@
         GrContext* context, AHardwareBuffer* hardwareBuffer,
         int width, int height, GrPixelConfig config,
         GrAHardwareBufferImageGenerator::DeleteImageProc* deleteProc,
-        GrAHardwareBufferImageGenerator::DeleteImageCtx* deleteCtx) {
+        GrAHardwareBufferImageGenerator::DeleteImageCtx* deleteCtx,
+        bool isProtectedContent) {
     if (context->abandoned() || kOpenGL_GrBackend != context->contextPriv().getBackend()) {
         // Check if GrContext is not abandoned and the backend is GL.
         return GrBackendTexture();
     }
+    bool createProtectedImage = isProtectedContent && can_import_protected_content(context);
     return make_gl_backend_texture(context, hardwareBuffer, width, height, config, deleteProc,
-                                   deleteCtx);
+                                   deleteCtx, createProtectedImage);
 }
 
 static void free_backend_texture(GrBackendTexture* backendTexture) {
@@ -295,9 +329,11 @@
     AHardwareBuffer_acquire(hardwareBuffer);
 
     GrTexture** ownedTexturePtr = &fOwnedTexture;
+    const bool isProtectedContent = fIsProtectedContent;
 
     fCachedProxy = proxyProvider->createLazyProxy(
-            [context, hardwareBuffer, width, height, pixelConfig, ownedTexturePtr]
+            [context, hardwareBuffer, width, height, pixelConfig, ownedTexturePtr,
+             isProtectedContent]
             (GrResourceProvider* resourceProvider) {
                 if (!resourceProvider) {
                     AHardwareBuffer_release(hardwareBuffer);
@@ -312,7 +348,8 @@
                 GrBackendTexture backendTex = make_backend_texture(context, hardwareBuffer,
                                                                    width, height, pixelConfig,
                                                                    &deleteImageProc,
-                                                                   &deleteImageCtx);
+                                                                   &deleteImageCtx,
+                                                                   isProtectedContent);
                 if (!backendTex.isValid()) {
                     return sk_sp<GrTexture>();
                 }
diff --git a/src/gpu/GrAHardwareBufferImageGenerator.h b/src/gpu/GrAHardwareBufferImageGenerator.h
index 58b5abf..3c6f678 100644
--- a/src/gpu/GrAHardwareBufferImageGenerator.h
+++ b/src/gpu/GrAHardwareBufferImageGenerator.h
@@ -47,7 +47,8 @@
                                             bool willNeedMipMaps) override;
 
 private:
-    GrAHardwareBufferImageGenerator(const SkImageInfo&, AHardwareBuffer*, SkAlphaType);
+    GrAHardwareBufferImageGenerator(const SkImageInfo&, AHardwareBuffer*, SkAlphaType,
+                                    bool isProtectedContent);
     void makeProxy(GrContext* context);
 
     void releaseTextureRef();
@@ -63,6 +64,7 @@
     uint32_t             fOwningContextID = SK_InvalidGenID;
 
     sk_sp<GrTextureProxy> fCachedProxy;
+    const bool fIsProtectedContent;
 
     typedef SkImageGenerator INHERITED;
 };