egl: implement EGL_EXT_protected_surface support
Reviewed-by: Eric Engestrom <eric@engestrom.ch>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5096>
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 76c50ad..94406dc 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1367,6 +1367,7 @@
* 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 @@
#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 e0d7b05..a2ffb60 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -1017,6 +1017,10 @@
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 a0760df..2944a5d 100644
--- a/src/egl/drivers/dri2/platform_drm.c
+++ b/src/egl/drivers/dri2/platform_drm.c
@@ -251,12 +251,16 @@
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 cd43fb2..c0b26c4 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -574,6 +574,13 @@
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 40d203c..e117105 100644
--- a/src/egl/drivers/dri2/platform_x11_dri3.c
+++ b/src/egl/drivers/dri2/platform_x11_dri3.c
@@ -183,6 +183,15 @@
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 405be03..56dafca 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -496,6 +496,7 @@
_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 @@
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 @@
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 87415f8..46c3008 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -106,6 +106,7 @@
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 16a718a..9faa800 100644
--- a/src/egl/main/eglsurface.c
+++ b/src/egl/main/eglsurface.c
@@ -303,6 +303,14 @@
}
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 @@
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 @@
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 a98bc8e..7f419cb 100644
--- a/src/egl/main/eglsurface.h
+++ b/src/egl/main/eglsurface.h
@@ -169,6 +169,8 @@
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 3ed5586..ead1c7d 100644
--- a/src/gallium/frontends/dri/dri2.c
+++ b/src/gallium/frontends/dri/dri2.c
@@ -1018,6 +1018,8 @@
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 e84c955..d9d2984 100644
--- a/src/gallium/frontends/dri/dri_query_renderer.c
+++ b/src/gallium/frontends/dri/dri_query_renderer.c
@@ -67,6 +67,13 @@
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 bc68f66..b563474 100644
--- a/src/gbm/backends/dri/gbm_dri.c
+++ b/src/gbm/backends/dri/gbm_dri.c
@@ -1142,6 +1142,8 @@
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 8cb928b..5801cd5 100644
--- a/src/gbm/main/gbm.h
+++ b/src/gbm/main/gbm.h
@@ -238,6 +238,12 @@
* 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 82b8cba..ccf8d17 100644
--- a/src/loader/loader_dri3_helper.c
+++ b/src/loader/loader_dri3_helper.c
@@ -1419,7 +1419,9 @@
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 3d50852..5191c89 100644
--- a/src/loader/loader_dri3_helper.h
+++ b/src/loader/loader_dri3_helper.h
@@ -168,6 +168,8 @@
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,