From mboxrd@z Thu Jan 1 00:00:00 1970 From: Marius Vlad Subject: Re: [PATCH v3] prime_mmap_kms: show case dma-buf new API and processes restrictions Date: Fri, 6 May 2016 13:40:49 +0300 Message-ID: <20160506104039.GA32322@mcvlad-wk.rb.intel.com> References: <1462487528-25551-1-git-send-email-tiago.vignatti@intel.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0424056265==" Return-path: Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by gabe.freedesktop.org (Postfix) with ESMTP id E06466EA71 for ; Fri, 6 May 2016 10:37:49 +0000 (UTC) In-Reply-To: <1462487528-25551-1-git-send-email-tiago.vignatti@intel.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" To: Tiago Vignatti Cc: intel-gfx@lists.freedesktop.org List-Id: intel-gfx@lists.freedesktop.org --===============0424056265== Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="eJnRUKwClWJh1Khz" Content-Disposition: inline --eJnRUKwClWJh1Khz Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Thu, May 05, 2016 at 07:32:08PM -0300, Tiago Vignatti wrote: > dma-buf new API consists of: >=20 > - mmap(dma_buf_fd, ...): the ability to map a dma-buf file-descriptor of a > graphics buffer to the userspace, and more importantly, to actually write= on > the mapped pointer (which was not possible before). It=E2=80=99s worth no= ting that the > Direct Rendering Manager (DRM) and the hardware driver implementation are > fundamentally important to safely export the graphics handle to be mapped. >=20 > - ioctl(dma_buf_fd, DMA_BUF_IOCTL_SYNC, &args): cache coherency managemen= t in > cases where the CPU and GPU devices are being accessed through dma-buf at= the > same time. Coherency markers, which forward directly to existing dma-buf > device drivers vfunc hooks, are exposed to the userspace through the > DMA_BUF_IOCTL_SYNC ioctl and have to be used before and after the mapped = area > is accessed. This is fundamentally important in hardware architectures wh= ere > the graphics engine and the CPU cores don't share caches but also importa= nt in > other type of hardware where the memory hierarchy is (most of the time) > coherent. More details can be found in this patch set: >=20 > http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id= =3Dc11e391da2a8fe973c3c2398452000bed505851e >=20 > v2: use uint32_t for color type, increment the variable and add > --interactive-debug=3Dpaint > v3: use igt_display_commit() to mode set the crtc so the rectangle is sho= wn > painted; also added Testcase description on the beginning of the file. >=20 > Signed-off-by: Tiago Vignatti > --- >=20 > OBS: v2 was sent privately to Marius only. Sorry. >=20 > tests/Makefile.sources | 1 + > tests/prime_mmap_kms.c | 264 +++++++++++++++++++++++++++++++++++++++++++= ++++++ > 2 files changed, 265 insertions(+) > create mode 100644 tests/prime_mmap_kms.c >=20 > diff --git a/tests/Makefile.sources b/tests/Makefile.sources > index 9ea9b5b..7b5f316 100644 > --- a/tests/Makefile.sources > +++ b/tests/Makefile.sources > @@ -113,6 +113,7 @@ TESTS_progs_M =3D \ > pm_sseu \ > prime_mmap \ > prime_mmap_coherency \ > + prime_mmap_kms \ > prime_self_import \ > template \ > $(NULL) > diff --git a/tests/prime_mmap_kms.c b/tests/prime_mmap_kms.c > new file mode 100644 > index 0000000..ef2d715 > --- /dev/null > +++ b/tests/prime_mmap_kms.c > @@ -0,0 +1,264 @@ > +/* > + * Copyright =C2=A9 2016 Intel Corporation > + * > + * Permission is hereby granted, free of charge, to any person obtaining= a > + * copy of this software and associated documentation files (the "Softwa= re"), > + * to deal in the Software without restriction, including without limita= tion > + * the rights to use, copy, modify, merge, publish, distribute, sublicen= se, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the = next > + * paragraph) shall be included in all copies or substantial portions of= the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRE= SS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILI= TY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SH= ALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR = OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISI= NG > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER D= EALINGS > + * IN THE SOFTWARE. > + * > + * Authors: > + * Tiago Vignatti > + */ > + > +/* > + * Testcase: show case dma-buf new API and processes restrictions. Most = likely > + * you want to run like ./prime_mmap_kms --interactive-debug=3Dpaint, to= see the > + * actual rectangle painted on the screen. > + */ > + > +#include "igt.h" > + > +IGT_TEST_DESCRIPTION( > + "Efficiently sharing CPU and GPU buffers"); > + > +/* > + * render_process_t: > + * > + * Render is basically a user-space regular client. It's the unprivileged > + * process with limited system accesses. > + * > + * Worth note the vendor-independent characteristic, meaning that the > + * client doesn't need to perform any vendor specific calls for buffer > + * handling. Mesa GBM library is a counter-example because, even though = its API > + * is vendor-independent, under-the-hood the library actually calls vend= or > + * specific ioctls, which is not really sandboxable and not the goal her= e. > + */ > +typedef struct { > + int prime_fd; > + size_t size; > + int width; > + int height; > +} render_process_t; > + > +typedef struct { > + int x; > + int y; > + int w; > + int h; > +} rect_t; > + > +/* set ptr in a linear view */ > +static void set_pixel(void *_ptr, int index, uint32_t color, int bpp) > +{ > + if (bpp =3D=3D 16) { > + uint16_t *ptr =3D _ptr; > + ptr[index] =3D color; > + } else if (bpp =3D=3D 32) { > + uint32_t *ptr =3D _ptr; > + ptr[index] =3D color; > + } else { > + igt_assert_f(false, "bpp: %d\n", bpp); > + } > +} > + > +static void paint(render_process_t *render) > +{ > + void *frame; > + rect_t rect =3D { > + .x =3D 200, > + .y =3D 200, > + .w =3D render->width / 4, > + .h =3D render->height / 4, > + }; > + uint32_t color =3D 0xFF; > + int stride, bpp; > + int x, y, line_begin; > + > + frame =3D mmap(NULL, render->size, PROT_READ | PROT_WRITE, MAP_SHARED, > + render->prime_fd, 0); > + igt_assert(frame !=3D MAP_FAILED); > + > + /* TODO: what's the mmap'ed buffer semantics on tiling, format etc. How > + * does the client know whether that the BO was created X-tiled, > + * Y-tiled and how it will map back? This is something we need to > + * address in this API still. */ > + stride =3D render->width * 4; > + bpp =3D 32; > + > + /* ioctls to keep up the GPU <-> CPU coherency */ > + prime_sync_start(render->prime_fd, true); > + > + /* the actual painting phase happens here */ > + for (y =3D rect.y; y < rect.y + rect.h; y++) { > + line_begin =3D y * stride / (bpp / 8); > + for (x =3D rect.x; x < rect.x + rect.w; x++) > + set_pixel(frame, line_begin + x, color, bpp); > + } > + > + prime_sync_end(render->prime_fd, true); > + munmap(frame, render->size); > +} > + > +static void init_renderer(int prime_fd, int fb_size, int width, int heig= ht) > +{ > + render_process_t render; > + > + render.prime_fd =3D prime_fd; > + render.size =3D fb_size; > + render.width =3D width; > + render.height =3D height; > + paint(&render); > +} > + > +/* > + * gpu_process_t: > + * > + * GPU process is the privileged process and has access to the system gr= aphics > + * routines, like DRM, display management and driver accesses. > + */ > +typedef struct { > + int drm_fd; > + igt_display_t display; > + struct igt_fb fb; > + igt_output_t *output; > + igt_plane_t *primary; > + enum pipe pipe; > +} gpu_process_t; > + > +static void cleanup_crtc(gpu_process_t *gpu) > +{ > + igt_display_t *display =3D &gpu->display; > + igt_output_t *output =3D gpu->output; > + > + igt_plane_set_fb(gpu->primary, NULL); > + > + igt_output_set_pipe(output, PIPE_ANY); > + igt_display_commit(display); > + > + igt_remove_fb(gpu->drm_fd, &gpu->fb); > +} > + > +static void set_crtc(gpu_process_t *gpu) > +{ > + igt_display_t *display =3D &gpu->display; > + > + igt_display_commit(display); > +} > + > +static bool prepare_crtc(gpu_process_t *gpu) > +{ > + igt_display_t *display =3D &gpu->display; > + igt_output_t *output =3D gpu->output; > + drmModeModeInfo *mode; > + > + /* select the pipe we want to use */ > + igt_output_set_pipe(output, gpu->pipe); > + igt_display_commit(display); > + > + if (!output->valid) { > + igt_output_set_pipe(output, PIPE_ANY); > + igt_display_commit(display); > + return false; > + } > + > + mode =3D igt_output_get_mode(output); > + > + /* create a white fb and flip to it */ > + igt_create_color_fb(gpu->drm_fd, mode->hdisplay, mode->vdisplay, > + DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE, > + 1.0, 1.0, 1.0, &gpu->fb); > + > + gpu->primary =3D igt_output_get_plane(output, IGT_PLANE_PRIMARY); > + > + igt_plane_set_fb(gpu->primary, &gpu->fb); > + igt_display_commit(display); > + > + return true; > +} > + > +/* > + * The idea is to create a BO (in this case the framebuffer's) in one pr= ocess, > + * export and pass its prime fd to another process, which in turn uses t= he fd > + * to map and write. This is Chrome-like architectures, where the Web co= ntent > + * (a "tab" or the "unprivileged process") maps and CPU-paints a buffer,= which > + * was previously allocated in the GPU process ("privileged process"). > + */ > +static void run_test(gpu_process_t *gpu) > +{ > + igt_display_t *display =3D &gpu->display; > + igt_output_t *output; > + enum pipe pipe; > + int prime_fd; > + > + for_each_connected_output(display, output) { > + gpu->output =3D output; > + for_each_pipe(display, pipe) { > + gpu->pipe =3D pipe; > + > + if (!prepare_crtc(gpu)) > + continue; > + > + prime_fd =3D prime_handle_to_fd_for_mmap(gpu->drm_fd, > + gpu->fb.gem_handle); > + igt_skip_on(prime_fd =3D=3D -1 && errno =3D=3D EINVAL); > + > + /* Note that it only shares the dma-buf fd and some > + * other basic info */ > + igt_fork(renderer_no, 1) { > + init_renderer(prime_fd, gpu->fb.size, gpu->fb.width, > + gpu->fb.height); > + } > + igt_waitchildren(); > + > + set_crtc(gpu); Doing another commit doesn't really help. With or without same thing. > + igt_debug_wait_for_keypress("paint"); Or you can change this with a sleep. > + cleanup_crtc(gpu); > + > + /* once is enough */ > + return; > + } > + } > + > + igt_skip("no valid crtc/connector combinations found\n"); > +} > + > +igt_main > +{ > + gpu_process_t gpu; > + > + igt_skip_on_simulation(); > + > + igt_fixture { > + gpu.drm_fd =3D drm_open_driver_master(DRIVER_INTEL); > + > + kmstest_set_vt_graphics_mode(); > + > + igt_require_pipe_crc(); > + > + igt_display_init(&gpu.display, gpu.drm_fd); > + } > + Wouldn't make sense to have a skip_on in case we're running an older kernel? (i.e., skip_on if DMA_BUF_IOCTL_SYNC ioctl not present) > + igt_subtest("buffer-sharing") > + run_test(&gpu); > + > + igt_fixture { > + igt_display_fini(&gpu.display); > + close(gpu.drm_fd); > + } > + > + igt_exit(); > +} > --=20 > 2.7.4 >=20 --eJnRUKwClWJh1Khz Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAEBAgAGBQJXLHSuAAoJELmLWIAQzyE+R40IAIFjrDNN9CUwQ3WLTxfTCmtH smHBI+bu9H1OIsK5U5eu4ESsGKZjEkAUuUNNI0el7a2lOEgTEiVRXqBsWckt5fYR Ys/50BC74amIPDOpeNFLNYtNa2H+k/xXzdbBKkJfTcj3nicxawnBKasaHWayv+1K ZXVnBQv3ocbvmQ8uZYKO4oevVd1BtTW0n1bbR0/B3gqYIMggeW+EBoBHwKJ2ZVXe Gc6SOBRKJPvwwvFJJEJWKCkUbvsI5Bu9PdeOb7RuF+CAYZzQfJ4ZjU1p/AhbbMlO CHcMxO4/BiByIinCs0C20oKoQqAKKz3oTRgaFUaVl+C66MTmw3hnQgCwTBv9xfQ= =9PCh -----END PGP SIGNATURE----- --eJnRUKwClWJh1Khz-- --===============0424056265== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KSW50ZWwtZ2Z4 IG1haWxpbmcgbGlzdApJbnRlbC1nZnhAbGlzdHMuZnJlZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlz dHMuZnJlZWRlc2t0b3Aub3JnL21haWxtYW4vbGlzdGluZm8vaW50ZWwtZ2Z4Cg== --===============0424056265==--