diff options
author | Frediano Ziglio <fziglio@redhat.com> | 2017-03-31 14:54:36 +0100 |
---|---|---|
committer | Frediano Ziglio <freddy77@gmail.com> | 2021-06-14 11:56:23 +0100 |
commit | dc493c956de6e9aa9e609b91e206672be692b007 (patch) | |
tree | 990921f8f2a931ede94369812d73600e5742af75 | |
parent | aca1aff9d7270b58518b4136750a00c74532318e (diff) |
Implements DRM prime checks in GStreamer test utility
Allows to specify DRM as image format.
This to make sure that video encoders can support such
format as input.
There is no point in supporting this using GStreamer 0.10
as it does not support nor OpenGL nor VAAPI.
Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | meson.build | 1 | ||||
-rw-r--r-- | server/tests/Makefile.am | 17 | ||||
-rw-r--r-- | server/tests/egl-helpers.c | 63 | ||||
-rw-r--r-- | server/tests/egl-helpers.h | 34 | ||||
-rw-r--r-- | server/tests/meson.build | 7 | ||||
-rw-r--r-- | server/tests/test-gst.cpp | 114 | ||||
-rwxr-xr-x | server/tests/test-video-encoders | 2 |
8 files changed, 173 insertions, 69 deletions
diff --git a/configure.ac b/configure.ac index 21e915ce..fddaeca3 100644 --- a/configure.ac +++ b/configure.ac @@ -221,6 +221,10 @@ PKG_CHECK_MODULES(EPOXY, epoxy) AC_SUBST(EPOXY_CFLAGS) AC_SUBST(EPOXY_LIBS) +PKG_CHECK_MODULES(GBM, gbm) +AC_SUBST(GBM_CFLAGS) +AC_SUBST(GBM_LIBS) + AC_CHECK_LIB(jpeg, jpeg_destroy_decompress, AC_MSG_CHECKING([for jpeglib.h]) AC_TRY_CPP( diff --git a/meson.build b/meson.build index 4b7e90f9..e418cd62 100644 --- a/meson.build +++ b/meson.build @@ -188,6 +188,7 @@ if spice_has_egl spice_server_config_data.set('HAVE_EPOXY_EGL_H', '1') spice_server_config_data.set('HAVE_EGL', '1') # FIXME: Use single define? spice_server_deps += dependency('epoxy') + spice_server_deps += dependency('gbm') endif # diff --git a/server/tests/Makefile.am b/server/tests/Makefile.am index 3a2c0976..6cc536b0 100644 --- a/server/tests/Makefile.am +++ b/server/tests/Makefile.am @@ -174,6 +174,16 @@ test_gst_CPPFLAGS = \ $(GSTREAMER_0_10_CFLAGS) \ $(GSTREAMER_1_0_CFLAGS) \ $(NULL) +test_gst_LDADD = \ + $(LDADD) \ + $(NULL) +if HAVE_GSTREAMER_1_0 +test_gst_SOURCES += \ + egl-helpers.c \ + egl-helpers.h \ + $(NULL) +test_gst_LDADD += $(GBM_LIBS) +endif endif EXTRA_DIST += test-video-encoders @@ -181,3 +191,10 @@ EXTRA_DIST += test-video-encoders if HAVE_SASL check_PROGRAMS += test-sasl endif + +# distribute these in any case, even if compilation from them is disabled +EXTRA_DIST += \ + test-gst.c \ + egl-helpers.c \ + egl-helpers.h \ + $(NULL) diff --git a/server/tests/egl-helpers.c b/server/tests/egl-helpers.c index 584dd1b0..0c4bb225 100644 --- a/server/tests/egl-helpers.c +++ b/server/tests/egl-helpers.c @@ -14,21 +14,39 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ -#include "qemu/osdep.h" +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> #include <glob.h> #include <dirent.h> +#include <err.h> +#include <glib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <gbm.h> +#include <epoxy/gl.h> +#include <epoxy/egl.h> + +#include "egl-helpers.h" -#include "qemu/error-report.h" -#include "ui/egl-helpers.h" +EGLDisplay qemu_egl_display; +EGLContext qemu_egl_rn_ctx; +static EGLConfig qemu_egl_config; -EGLDisplay *qemu_egl_display; -EGLConfig qemu_egl_config; +static int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug); +static EGLContext qemu_egl_init_ctx(void); /* ---------------------------------------------------------------------- */ static bool egl_gles; static int egl_debug; +#define error_report(...) errx(1, __VA_ARGS__) #define egl_dbg(_x ...) \ do { \ if (egl_debug) { \ @@ -38,11 +56,8 @@ static int egl_debug; /* ---------------------------------------------------------------------- */ -#ifdef CONFIG_OPENGL_DMABUF - -int qemu_egl_rn_fd; -struct gbm_device *qemu_egl_rn_gbm_dev; -EGLContext qemu_egl_rn_ctx; +static int qemu_egl_rn_fd = -1; +static struct gbm_device *qemu_egl_rn_gbm_dev; static int qemu_egl_rendernode_open(const char *rendernode) { @@ -162,34 +177,6 @@ int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc) return fd; } -#endif /* CONFIG_OPENGL_DMABUF */ - -/* ---------------------------------------------------------------------- */ - -EGLSurface qemu_egl_init_surface_x11(EGLContext ectx, Window win) -{ - EGLSurface esurface; - EGLBoolean b; - - egl_dbg("eglCreateWindowSurface (x11 win id 0x%lx) ...\n", - (unsigned long) win); - esurface = eglCreateWindowSurface(qemu_egl_display, - qemu_egl_config, - (EGLNativeWindowType)win, NULL); - if (esurface == EGL_NO_SURFACE) { - error_report("egl: eglCreateWindowSurface failed"); - return NULL; - } - - b = eglMakeCurrent(qemu_egl_display, esurface, esurface, ectx); - if (b == EGL_FALSE) { - error_report("egl: eglMakeCurrent failed"); - return NULL; - } - - return esurface; -} - /* ---------------------------------------------------------------------- */ int qemu_egl_init_dpy(EGLNativeDisplayType dpy, bool gles, bool debug) diff --git a/server/tests/egl-helpers.h b/server/tests/egl-helpers.h new file mode 100644 index 00000000..8e530692 --- /dev/null +++ b/server/tests/egl-helpers.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2015-2016 Gerd Hoffmann <kraxel@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef EGL_HELPERS_H_ +#define EGL_HELPERS_H_ + +#include <epoxy/gl.h> +#include <epoxy/egl.h> +#include <spice/macros.h> + +SPICE_BEGIN_DECLS + +int egl_rendernode_init(const char *rendernode); +int egl_get_fd_for_texture(uint32_t tex_id, EGLint *stride, EGLint *fourcc); + +extern EGLDisplay qemu_egl_display; +extern EGLContext qemu_egl_rn_ctx; + +SPICE_END_DECLS + +#endif diff --git a/server/tests/meson.build b/server/tests/meson.build index 4f150a0b..536f8403 100644 --- a/server/tests/meson.build +++ b/server/tests/meson.build @@ -93,8 +93,13 @@ foreach t : tests else language = 'c' endif + if test_name == 'test-gst' and spice_has_egl + add_sources = ['egl-helpers.c', 'egl-helpers.h'] + else + add_sources = [] + endif exe = executable(test_name, - sources : '@0@.@1@'.format(test_name, language), + sources : ['@0@.@1@'.format(test_name, language)] + add_sources, link_with : test_libs, include_directories : test_lib_include, c_args : ['-DSPICE_TOP_SRCDIR="@0@"'.format(meson.source_root())], diff --git a/server/tests/test-gst.cpp b/server/tests/test-gst.cpp index 3c87d161..f0c72df2 100644 --- a/server/tests/test-gst.cpp +++ b/server/tests/test-gst.cpp @@ -34,6 +34,7 @@ #include "video-encoder.h" #include "spice-bitmap-utils.h" #include "egl.h" +#include "egl-helpers.h" #include "reds.h" // reds_get_mm_time static const char program_description[] = @@ -147,6 +148,11 @@ static VideoEncoder *video_encoder = NULL; // image settings static gboolean top_down = FALSE; static SpiceBitmapFmt bitmap_format = SPICE_BITMAP_FMT_32BIT; +static bool use_drm = false; +#ifndef HAVE_GSTREAMER_0_10 +static SpiceDrmPrimeContext *drm_context = NULL; +static void *drm_egl_context = NULL; +#endif static gint image_split_lines = 60000; static gboolean clipping_type_computed = FALSE; @@ -172,7 +178,7 @@ static int global_test_error = 0; static void compute_clipping_rect(GstSample *sample); static void parse_clipping(const char *clipping); -static TestFrame *gst_to_spice_frame(GstSample *sample); +static TestFrame *gst_to_spice_frame(GstSample *sample, bool allow_drm); static void image_free(SpiceImageEx *image); static void frame_ref(TestFrame *frame); static void frame_unref(TestFrame *frame); @@ -207,7 +213,7 @@ input_frames(GstSample *sample, void *param) uint32_t frame_mm_time = reds_get_mm_time(); // convert frame to SpiceBitmap/DRM prime - TestFrame *frame = gst_to_spice_frame(sample); + TestFrame *frame = gst_to_spice_frame(sample, true); // send frame to our video encoder (must be from a single thread) VideoEncodeResults res = @@ -262,9 +268,9 @@ input_frames(GstSample *sample, void *param) static GstFlowReturn output_frames(GstSample *sample, void *param) { - TestFrame *curr_frame = gst_to_spice_frame(sample); + TestFrame *curr_frame = gst_to_spice_frame(sample, false); - // TODO support DRM prime in the future + // this should be true as we pass false to gst_to_spice_frame spice_assert(curr_frame->image->descriptor.type == SPICE_IMAGE_TYPE_BITMAP); // get first frame queued @@ -350,7 +356,7 @@ int main(int argc, char *argv[]) { "top-down", 0, 0, G_OPTION_ARG_NONE, &top_down, "Image encoded as top-down", NULL }, { "format", 'f', 0, G_OPTION_ARG_STRING, &image_format, - "Image format (16BIT/24BIT/32BIT/RGBA)", "FMT" }, + "Image format (16BIT/24BIT/32BIT/RGBA/DRM)", "FMT" }, { "encoder", 'e', 0, G_OPTION_ARG_STRING, &encoder_name, "Encoder to use", "ENC" }, { "use-hw-encoder", 0, 0, G_OPTION_ARG_NONE, &use_hw_encoder, @@ -393,7 +399,17 @@ int main(int argc, char *argv[]) } } - if (image_format != NULL) { + if (image_format != NULL && strcmp(image_format, "DRM") == 0) { +#ifdef HAVE_GSTREAMER_0_10 + g_printerr("DRM not available using Gstreamer 0.10\n"); + exit(123); +#else + use_drm = true; + bitmap_format = SPICE_BITMAP_FMT_24BIT; + spice_assert(egl_rendernode_init(NULL) == 0); + drm_context = drm_prime_context_new(qemu_egl_display); +#endif + } else if (image_format != NULL) { bitmap_format = get_bitmap_format(image_format); if (bitmap_format == SPICE_BITMAP_FMT_INVALID) { g_printerr("Invalid image format: %s\n", image_format); @@ -807,7 +823,7 @@ static convert_line_t convert_line32; static convert_line_t *get_convert_line(SpiceBitmapFmt format); static SpiceImageEx * -gst_to_spice_image(GstSample *sample) +gst_to_spice_image(GstSample *sample, bool allow_drm) { GstCaps *caps = gst_sample_get_caps(sample); spice_assert(caps); @@ -819,34 +835,74 @@ gst_to_spice_image(GstSample *sample) spice_assert(gst_structure_get_int(s, "width", &width) && gst_structure_get_int(s, "height", &height)); - SpiceImageEx *image = g_new0(SpiceImageEx, 1); - image->descriptor.type = SPICE_IMAGE_TYPE_BITMAP; - image->descriptor.width = width; - image->descriptor.height = height; - SpiceBitmap *bitmap = &image->image.u.bitmap; - bitmap->format = bitmap_format; - bitmap->flags = top_down ? SPICE_BITMAP_FLAGS_TOP_DOWN : 0; - bitmap->x = width; - bitmap->y = height; - bitmap->stride = compute_stride(width, (SpiceBitmapFmt) bitmap->format); - bitmap->data = chunks_alloc(bitmap->stride, height, image_split_lines); - GstBuffer *buffer = gst_sample_get_buffer(sample); GstMapInfo mapinfo; if (!gst_buffer_map(buffer, &mapinfo, GST_MAP_READ)) { spice_error("GStreamer error: could not map the buffer"); } - // convert image - gint y; - convert_line_t *convert_line = get_convert_line((SpiceBitmapFmt) bitmap->format); - for (y = 0; y < height; ++y) { - convert_line(bitmap_get_line(bitmap, y), - mapinfo.data + y * width * 4, - width); + SpiceImageEx *image = g_new0(SpiceImageEx, 1); + image->descriptor.width = width; + image->descriptor.height = height; + if (allow_drm && use_drm) { +#ifdef HAVE_GSTREAMER_0_10 + spice_assert(false); +#else + image->descriptor.type = SPICE_IMAGE_TYPE_DRM_PRIME; + SpiceDrmPrime *drm_prime = &image->drm_prime; + drm_prime->width = width; + drm_prime->height = height; + + EGLBoolean b; + EGLDisplay egl_display = drm_context->egl_display; + + spice_assert(egl_display); + spice_assert(egl_display == qemu_egl_display); + + // create texture and load + if (!drm_egl_context) { + drm_egl_context = egl_display_create_context(egl_display); + spice_assert(drm_egl_context); + } + b = eglMakeCurrent(qemu_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, drm_egl_context); + spice_assert(b); + GLuint tex_id = 0; + glGenTextures(1, &tex_id); + spice_assert(tex_id != 0); + glBindTexture(GL_TEXTURE_2D, tex_id); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, mapinfo.data); + + EGLint stride, drm_fourcc_format; + drm_prime->drm_dma_buf_fd = egl_get_fd_for_texture(tex_id, &stride, &drm_fourcc_format); + spice_assert(drm_prime->drm_dma_buf_fd >= 0); + + glDeleteTextures(1, &tex_id); + + drm_prime->stride = stride; + drm_prime->drm_fourcc_format = drm_fourcc_format; + drm_prime->context = drm_context; + drm_prime->flags = top_down ? 0: SPICE_GL_SCANOUT_FLAGS_Y0TOP; // TODO... sure ?? +#endif + } else { + image->descriptor.type = SPICE_IMAGE_TYPE_BITMAP; + SpiceBitmap *bitmap = &image->image.u.bitmap; + bitmap->format = bitmap_format; + bitmap->flags = top_down ? SPICE_BITMAP_FLAGS_TOP_DOWN : 0; + bitmap->x = width; + bitmap->y = height; + bitmap->stride = compute_stride(width, (SpiceBitmapFmt) bitmap->format); + bitmap->data = chunks_alloc(bitmap->stride, height, image_split_lines); + + // convert image + gint y; + convert_line_t *convert_line = get_convert_line((SpiceBitmapFmt) bitmap->format); + for (y = 0; y < height; ++y) { + convert_line(bitmap_get_line(bitmap, y), + mapinfo.data + y * width * 4, + width); + } } gst_buffer_unmap(buffer, &mapinfo); - // TODO should we unref buffer ?? return image; } @@ -982,11 +1038,11 @@ get_bitmap_format(const char *format) } static TestFrame * -gst_to_spice_frame(GstSample *sample) +gst_to_spice_frame(GstSample *sample, bool allow_drm) { TestFrame *frame = g_new0(TestFrame, 1); frame->refs = 1; - frame->image = gst_to_spice_image(sample); + frame->image = gst_to_spice_image(sample, allow_drm); return frame; } diff --git a/server/tests/test-video-encoders b/server/tests/test-video-encoders index 039dd219..51ba6ae4 100755 --- a/server/tests/test-video-encoders +++ b/server/tests/test-video-encoders @@ -16,7 +16,7 @@ do for split in '' '--split-lines=40' do # TODO check if encoder is supported - for format in 16BIT 24BIT 32BIT RGBA + for format in DRM do base_test -f $format -e $encoder $clipping $split done |