Mesa (master): egl: implement EGL_EXT_protected_surface support

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Nov 2 09:38:49 UTC 2020


Module: Mesa
Branch: master
Commit: bd182777c8f2c4468568901ce92b1796674eb87d
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=bd182777c8f2c4468568901ce92b1796674eb87d

Author: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer at amd.com>
Date:   Mon May 11 18:26:30 2020 +0200

egl: implement EGL_EXT_protected_surface support

Reviewed-by: Eric Engestrom <eric at engestrom.ch>
Reviewed-by: Marek Olšák <marek.olsak at amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5096>

---

 include/GL/internal/dri_interface.h            |  3 +++
 src/egl/drivers/dri2/egl_dri2.c                |  4 ++++
 src/egl/drivers/dri2/platform_drm.c            |  8 ++++++--
 src/egl/drivers/dri2/platform_wayland.c        |  7 +++++++
 src/egl/drivers/dri2/platform_x11_dri3.c       |  9 +++++++++
 src/egl/main/eglapi.c                          | 11 +++++++++++
 src/egl/main/egldisplay.h                      |  1 +
 src/egl/main/eglsurface.c                      | 14 ++++++++++++++
 src/egl/main/eglsurface.h                      |  2 ++
 src/gallium/frontends/dri/dri2.c               |  2 ++
 src/gallium/frontends/dri/dri_query_renderer.c |  7 +++++++
 src/gbm/backends/dri/gbm_dri.c                 |  2 ++
 src/gbm/main/gbm.h                             |  6 ++++++
 src/loader/loader_dri3_helper.c                |  4 +++-
 src/loader/loader_dri3_helper.h                |  2 ++
 15 files changed, 79 insertions(+), 3 deletions(-)

diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 76c50ad334f..94406dcb97b 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1367,6 +1367,7 @@ struct __DRIdri2ExtensionRec {
  * could be read after a flush."
  */
 #define __DRI_IMAGE_USE_BACKBUFFER      0x0010
+#define __DRI_IMAGE_USE_PROTECTED       0x0020
 
 
 #define __DRI_IMAGE_TRANSFER_READ            0x1
@@ -1932,6 +1933,8 @@ typedef struct __DRIDriverVtableExtensionRec {
 #define   __DRI2_RENDERER_HAS_CONTEXT_PRIORITY_MEDIUM         (1 << 1)
 #define   __DRI2_RENDERER_HAS_CONTEXT_PRIORITY_HIGH           (1 << 2)
 
+#define __DRI2_RENDERER_HAS_PROTECTED_CONTENT                 0x000e
+
 typedef struct __DRI2rendererQueryExtensionRec __DRI2rendererQueryExtension;
 struct __DRI2rendererQueryExtensionRec {
    __DRIextension base;
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index e0d7b05131c..a2ffb60e3bf 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -1017,6 +1017,10 @@ dri2_setup_screen(_EGLDisplay *disp)
 
    if (dri2_dpy->buffer_damage && dri2_dpy->buffer_damage->set_damage_region)
       disp->Extensions.KHR_partial_update = EGL_TRUE;
+
+   disp->Extensions.EXT_protected_content =
+      dri2_renderer_query_integer(dri2_dpy,
+                                  __DRI2_RENDERER_HAS_PROTECTED_CONTENT);
 }
 
 void
diff --git a/src/egl/drivers/dri2/platform_drm.c b/src/egl/drivers/dri2/platform_drm.c
index a0760dfebbb..2944a5d7ad4 100644
--- a/src/egl/drivers/dri2/platform_drm.c
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -251,12 +251,16 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
                                                             surf->base.format,
                                                             surf->base.modifiers,
                                                             surf->base.count);
-      else
+      else {
+         unsigned flags = surf->base.flags;
+         if (dri2_surf->base.ProtectedContent)
+            flags |= GBM_BO_USE_PROTECTED;
          dri2_surf->back->bo = gbm_bo_create(&dri2_dpy->gbm_dri->base,
                                              surf->base.width,
                                              surf->base.height,
                                              surf->base.format,
-                                             surf->base.flags);
+                                             flags);
+      }
 
    }
    if (dri2_surf->back->bo == NULL)
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index cd43fb26d5e..c0b26c4b623 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -574,6 +574,13 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
 
    use_flags = __DRI_IMAGE_USE_SHARE | __DRI_IMAGE_USE_BACKBUFFER;
 
+   if (dri2_surf->base.ProtectedContent) {
+      /* Protected buffers can't be read from another GPU */
+      if (dri2_dpy->is_different_gpu)
+         return -1;
+      use_flags |= __DRI_IMAGE_USE_PROTECTED;
+   }
+
    if (dri2_dpy->is_different_gpu &&
        dri2_surf->back->linear_copy == NULL) {
       /* The LINEAR modifier should be a perfect alias of the LINEAR use
diff --git a/src/egl/drivers/dri2/platform_x11_dri3.c b/src/egl/drivers/dri2/platform_x11_dri3.c
index 40d203c9ec1..e117105fcb6 100644
--- a/src/egl/drivers/dri2/platform_x11_dri3.c
+++ b/src/egl/drivers/dri2/platform_x11_dri3.c
@@ -183,6 +183,15 @@ dri3_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf,
       goto cleanup_pixmap;
    }
 
+   if (dri3_surf->surf.base.ProtectedContent &&
+       dri2_dpy->is_different_gpu) {
+      _eglError(EGL_BAD_ALLOC, "dri3_surface_create");
+      goto cleanup_pixmap;
+   }
+
+   dri3_surf->loader_drawable.is_protected_content =
+      dri3_surf->surf.base.ProtectedContent;
+
    return &dri3_surf->surf.base;
 
  cleanup_pixmap:
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 405be0367d9..56dafca0d11 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -496,6 +496,7 @@ _eglCreateExtensionsString(_EGLDisplay *disp)
    _EGL_CHECK_EXTENSION(EXT_create_context_robustness);
    _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import);
    _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import_modifiers);
+   _EGL_CHECK_EXTENSION(EXT_protected_content);
    _EGL_CHECK_EXTENSION(EXT_surface_CTA861_3_metadata);
    _EGL_CHECK_EXTENSION(EXT_surface_SMPTE2086_metadata);
    _EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage);
@@ -890,6 +891,14 @@ eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
       RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
    if (read_surf && read_surf->Lost)
       RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
+   /* EGL_EXT_protected_surface spec says:
+    *     If EGL_PROTECTED_CONTENT_EXT attributes of read is EGL_TRUE and
+    *     EGL_PROTECTED_CONTENT_EXT attributes of draw is EGL_FALSE, an
+    *     EGL_BAD_ACCESS error is generated.
+    */
+   if (read_surf && read_surf->ProtectedContent &&
+       draw_surf && !draw_surf->ProtectedContent)
+      RETURN_EGL_ERROR(disp, EGL_BAD_ACCESS, EGL_FALSE);
 
    ret = disp->Driver->MakeCurrent(disp, draw_surf, read_surf, context);
 
@@ -1471,6 +1480,8 @@ eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
    native_pixmap_ptr = (void*) target;
 
    _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
+   if (surf->ProtectedContent)
+      RETURN_EGL_ERROR(disp, EGL_BAD_ACCESS, EGL_FALSE);
    ret = disp->Driver->CopyBuffers(disp, surf, native_pixmap_ptr);
 
    RETURN_EGL_EVAL(disp, ret);
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 87415f81296..46c3008b658 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -106,6 +106,7 @@ struct _egl_extensions
    EGLBoolean EXT_image_dma_buf_import;
    EGLBoolean EXT_image_dma_buf_import_modifiers;
    EGLBoolean EXT_pixel_format_float;
+   EGLBoolean EXT_protected_content;
    EGLBoolean EXT_surface_CTA861_3_metadata;
    EGLBoolean EXT_surface_SMPTE2086_metadata;
    EGLBoolean EXT_swap_buffers_with_damage;
diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c
index 16a718aa09e..9faa800d001 100644
--- a/src/egl/main/eglsurface.c
+++ b/src/egl/main/eglsurface.c
@@ -303,6 +303,14 @@ _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list)
          }
          surf->MipmapTexture = !!val;
          break;
+      case EGL_PROTECTED_CONTENT_EXT:
+         if (!disp->Extensions.EXT_protected_content) {
+            err = EGL_BAD_ATTRIBUTE;
+            break;
+         }
+         surf->ProtectedContent = val;
+         break;
+
       /* no pixmap surface specific attributes */
       default:
          err = EGL_BAD_ATTRIBUTE;
@@ -383,6 +391,7 @@ _eglInitSurface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type,
    surf->VGAlphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE;
    surf->VGColorspace = EGL_VG_COLORSPACE_sRGB;
    surf->GLColorspace = EGL_GL_COLORSPACE_LINEAR_KHR;
+   surf->ProtectedContent = EGL_FALSE;
 
    surf->MipmapLevel = 0;
    surf->MultisampleResolve = EGL_MULTISAMPLE_RESOLVE_DEFAULT;
@@ -581,6 +590,11 @@ _eglQuerySurface(_EGLDisplay *disp, _EGLSurface *surface,
    case EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT:
       *value = surface->HdrMetadata.max_fall;
       break;
+   case EGL_PROTECTED_CONTENT_EXT:
+      if (!disp->Extensions.EXT_protected_content)
+         return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
+      *value = surface->ProtectedContent;
+      break;
    default:
       return _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface");
    }
diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h
index a98bc8eb18c..7f419cbf7e3 100644
--- a/src/egl/main/eglsurface.h
+++ b/src/egl/main/eglsurface.h
@@ -169,6 +169,8 @@ struct _egl_surface
 
    EGLBoolean PostSubBufferSupportedNV;
 
+   EGLBoolean ProtectedContent;
+
    struct _egl_hdr_metadata HdrMetadata;
 
    void *NativeSurface;
diff --git a/src/gallium/frontends/dri/dri2.c b/src/gallium/frontends/dri/dri2.c
index 3ed55866ad7..ead1c7d25e5 100644
--- a/src/gallium/frontends/dri/dri2.c
+++ b/src/gallium/frontends/dri/dri2.c
@@ -1018,6 +1018,8 @@ dri2_create_image_common(__DRIscreen *_screen,
          return NULL;
       tex_usage |= PIPE_BIND_CURSOR;
    }
+   if (use & __DRI_IMAGE_USE_PROTECTED)
+      tex_usage |= PIPE_BIND_PROTECTED;
 
    img = CALLOC_STRUCT(__DRIimageRec);
    if (!img)
diff --git a/src/gallium/frontends/dri/dri_query_renderer.c b/src/gallium/frontends/dri/dri_query_renderer.c
index e84c955334d..d9d2984bd64 100644
--- a/src/gallium/frontends/dri/dri_query_renderer.c
+++ b/src/gallium/frontends/dri/dri_query_renderer.c
@@ -67,6 +67,13 @@ dri2_query_renderer_integer(__DRIscreen *_screen, int param,
       if (!value[0])
          return -1;
       return 0;
+   case __DRI2_RENDERER_HAS_PROTECTED_CONTENT:
+      value[0] =
+         screen->base.screen->get_param(screen->base.screen,
+                                        PIPE_CAP_DEVICE_PROTECTED_CONTENT);
+      if (!value[0])
+         return -1;
+      return 0;
    default:
       return driQueryRendererIntegerCommon(_screen, param, value);
    }
diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c
index bc68f66766e..b5634741554 100644
--- a/src/gbm/backends/dri/gbm_dri.c
+++ b/src/gbm/backends/dri/gbm_dri.c
@@ -1142,6 +1142,8 @@ gbm_dri_bo_create(struct gbm_device *gbm,
       dri_use |= __DRI_IMAGE_USE_CURSOR;
    if (usage & GBM_BO_USE_LINEAR)
       dri_use |= __DRI_IMAGE_USE_LINEAR;
+   if (usage & GBM_BO_USE_PROTECTED)
+      dri_use |= __DRI_IMAGE_USE_PROTECTED;
 
    /* Gallium drivers requires shared in order to get the handle/stride */
    dri_use |= __DRI_IMAGE_USE_SHARE;
diff --git a/src/gbm/main/gbm.h b/src/gbm/main/gbm.h
index 8cb928b9677..5801cd526a0 100644
--- a/src/gbm/main/gbm.h
+++ b/src/gbm/main/gbm.h
@@ -238,6 +238,12 @@ enum gbm_bo_flags {
     * Buffer is linear, i.e. not tiled.
     */
    GBM_BO_USE_LINEAR = (1 << 4),
+   /**
+    * Buffer is protected, i.e. encrypted and not readable by CPU or any
+    * other non-secure / non-trusted components nor by non-trusted OpenGL,
+    * OpenCL, and Vulkan applications.
+    */
+   GBM_BO_USE_PROTECTED = (1 << 5),
 };
 
 int
diff --git a/src/loader/loader_dri3_helper.c b/src/loader/loader_dri3_helper.c
index 82b8cbaaafe..ccf8d1795e7 100644
--- a/src/loader/loader_dri3_helper.c
+++ b/src/loader/loader_dri3_helper.c
@@ -1419,7 +1419,9 @@ dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int format,
                                                        format,
                                                        __DRI_IMAGE_USE_SHARE |
                                                        __DRI_IMAGE_USE_SCANOUT |
-                                                       __DRI_IMAGE_USE_BACKBUFFER,
+                                                       __DRI_IMAGE_USE_BACKBUFFER |
+                                                       (draw->is_protected_content ?
+                                                         __DRI_IMAGE_USE_PROTECTED : 0),
                                                        buffer);
 
       pixmap_buffer = buffer->image;
diff --git a/src/loader/loader_dri3_helper.h b/src/loader/loader_dri3_helper.h
index 3d50852ba86..5191c89e7f2 100644
--- a/src/loader/loader_dri3_helper.h
+++ b/src/loader/loader_dri3_helper.h
@@ -168,6 +168,8 @@ struct loader_dri3_drawable {
    unsigned int back_format;
    xcb_present_complete_mode_t last_present_mode;
 
+   bool is_protected_content;
+
    /* Currently protects the following fields:
     * event_cnd, has_event_waiter,
     * recv_sbc, ust, msc, recv_msc_serial,



More information about the mesa-commit mailing list