[Mesa-dev] [RFC 1/2] gallium: add renderonly driver

Christian Gmeiner christian.gmeiner at gmail.com
Sun Oct 18 09:00:45 PDT 2015


Hi Emil,

Thanks for the review!

2015-10-16 1:09 GMT+02:00 Emil Velikov <emil.l.velikov at gmail.com>:
> Hi Christian,
>
> I'm glad to see Thierry's work revived. Hopefully this will soon be
> the basis of many more drivers.

I need to look into egl on wayland issue and hope to gain deeper knowledge
about the problem.

>
> On 11 October 2015 at 16:09, Christian Gmeiner
> <christian.gmeiner at gmail.com> wrote:
>> This commit adds a generic renderonly driver library, which fullfille
>> the requirements for tegra and etnaviv. As a result it is possible to
>> run unmodified egl software directly (without any compositor) on
>> supported devices.
>>
>> In every use case we import a dumb buffer from scanout gpu into
>> the renderonly gpu.
>>
>> If the scanout hardware does support the used tiling format from the
>> renderonly gpu, a driver can define a function which is used to 'setup'
>> the needed tiling on that imported buffer. This functions gets called
>> during rendertarget resource creation.
>>
>> If the scanout hardware does not support the used tiling format we need
>> to create an extra rendertarget resource for the renderonly gpu.
>> During XXX we blit the renderonly rendertarget onto the imported dumb
>> buffer.
>>
> I'd assume you meant to add something over the XXX here :-P
>

For sure :)

> But seriously some people might not be too happy with the blit onto
> dumb buffer. Personally I ok, esp. since we don't have anything better
> atm.

What is the problem with doing such a blit?

>
> That aside, there are a few minor nitpicks below. With those sorted I
> believe the patch is good to land.

Good to hear.

>
>> We assume that the renderonly driver provides a blit function that is
>> capable of resolving the tilied into untiled one.
>>
>> Signed-off-by: Christian Gmeiner <christian.gmeiner at gmail.com>
>> ---
>>  configure.ac                                       |   1 +
>>  src/gallium/drivers/renderonly/Makefile.am         |  11 +
>>  src/gallium/drivers/renderonly/Makefile.sources    |   4 +
>>  .../drivers/renderonly/renderonly_context.c        | 721 +++++++++++++++++++++
>>  .../drivers/renderonly/renderonly_context.h        |  80 +++
>>  .../drivers/renderonly/renderonly_resource.c       | 296 +++++++++
>>  .../drivers/renderonly/renderonly_resource.h       | 101 +++
>>  src/gallium/drivers/renderonly/renderonly_screen.c | 178 +++++
>>  src/gallium/drivers/renderonly/renderonly_screen.h |  55 ++
>>  9 files changed, 1447 insertions(+)
>>  create mode 100644 src/gallium/drivers/renderonly/Makefile.am
>>  create mode 100644 src/gallium/drivers/renderonly/Makefile.sources
>>  create mode 100644 src/gallium/drivers/renderonly/renderonly_context.c
>>  create mode 100644 src/gallium/drivers/renderonly/renderonly_context.h
>>  create mode 100644 src/gallium/drivers/renderonly/renderonly_resource.c
>>  create mode 100644 src/gallium/drivers/renderonly/renderonly_resource.h
>>  create mode 100644 src/gallium/drivers/renderonly/renderonly_screen.c
>>  create mode 100644 src/gallium/drivers/renderonly/renderonly_screen.h
>>
>> diff --git a/configure.ac b/configure.ac
>> index 217281f..ea485b1 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -2361,6 +2361,7 @@ AC_CONFIG_FILES([Makefile
>>                 src/gallium/drivers/radeon/Makefile
>>                 src/gallium/drivers/radeonsi/Makefile
>>                 src/gallium/drivers/rbug/Makefile
>> +               src/gallium/drivers/renderonly/Makefile
>>                 src/gallium/drivers/softpipe/Makefile
>>                 src/gallium/drivers/svga/Makefile
>>                 src/gallium/drivers/trace/Makefile
>
> Don't recall of the top of my head but we might need the following
> hunk. Otherwise the files won't end up in the tarball and configure
> will scream at us.

I will check that. For the moment I did not look into that area.

>
> --- a/src/gallium/Makefile.am
> +++ b/src/gallium/Makefile.am
> @@ -109,6 +109,7 @@ EXTRA_DIST = \
>        docs \
>        README.portability \
>        SConscript \
> +       drivers/renderonly \
>        winsys/sw/gdi \
>        winsys/sw/hgl
>

Ok.

>> --- /dev/null
>> +++ b/src/gallium/drivers/renderonly/Makefile.sources
>> @@ -0,0 +1,4 @@
>> +C_SOURCES := \
>> +       renderonly_context.c \
>> +       renderonly_resource.c \
>> +       renderonly_screen.c
> Please list all the sources (including the headers) in here, sorted
> alphabetically.

Ok.

>
>> --- /dev/null
>> +++ b/src/gallium/drivers/renderonly/renderonly_context.c
> [snip]
>> +static void
>> +renderonly_draw_vbo(struct pipe_context *pcontext,
>> +              const struct pipe_draw_info *pinfo)
>> +{
>> +       struct renderonly_context *context = to_renderonly_context(pcontext);
>> +       struct pipe_draw_info info;
>> +
>> +       if (pinfo && pinfo->indirect) {
> Can pinfo really be null here ?
>
>> +               memcpy(&info, pinfo, sizeof(info));
>> +               info.indirect = renderonly_resource_unwrap(info.indirect);
> During the unwrapping sometimes we're using the base object sometimes
> the wrapped one. Can we use just the latter ? It should minimize the
> (brief) 'wtf !?' moments.
>

Ok.

> [snip]
>> +static void
>> +renderonly_set_framebuffer_state(struct pipe_context *pcontext,
>> +                           const struct pipe_framebuffer_state *fb)
>> +{
>> +       struct renderonly_context *context = to_renderonly_context(pcontext);
>> +       struct pipe_framebuffer_state state;
>> +       unsigned i;
>> +
>> +       if (fb) {
> I doubt that fb can be NULL here.

Ok. I did not had a deep look at the call graph but did some kind of
defense programming here.

>
> [snip]
>> +static void
>> +renderonly_blit(struct pipe_context *pcontext,
>> +          const struct pipe_blit_info *pinfo)
>> +{
>> +       struct renderonly_context *context = to_renderonly_context(pcontext);
>> +       struct pipe_blit_info info;
>> +
>> +       if (pinfo) {
> Again pinfo cannot/shouldn't be NULL here.
>

Ok. Should I simply trust that it never can be NULL or can I add an assert?

> [snip]
>> +static struct pipe_sampler_view *
>> +renderonly_create_sampler_view(struct pipe_context *pcontext,
>> +                         struct pipe_resource *ptexture,
>> +                         const struct pipe_sampler_view *template)
>> +{
>> +       struct renderonly_resource *texture = to_renderonly_resource(ptexture);
>> +       struct renderonly_context *context = to_renderonly_context(pcontext);
>> +       struct renderonly_sampler_view *view;
>> +
>> +       view = calloc(1, sizeof(*view));
>> +       if (!view)
>> +               return NULL;
>> +
>> +       view->gpu = context->gpu->create_sampler_view(context->gpu,
>> +                                                     texture->gpu,
>> +                                                     template);
> Function can fail.
>

Correct. Will fix it.

> [snip]
>> +static void *
>> +renderonly_transfer_map(struct pipe_context *pcontext,
>> +                  struct pipe_resource *presource,
>> +                  unsigned level,
>> +                  unsigned usage,
>> +                  const struct pipe_box *box,
>> +                  struct pipe_transfer **ptransfer)
>> +{
>> +       struct renderonly_resource *resource = to_renderonly_resource(presource);
>> +       struct renderonly_context *context = to_renderonly_context(pcontext);
>> +       struct renderonly_transfer *transfer;
>> +
>> +       transfer = calloc(1, sizeof(*transfer));
>> +       if (!transfer)
>> +               return NULL;
>> +
>> +       transfer->map = context->gpu->transfer_map(context->gpu,
>> +                                                  resource->gpu,
>> +                                                  level,
>> +                                                  usage,
>> +                                                  box,
>> +                                                  &transfer->gpu);
> Ditto.

Correct. Will fix it.

>
>> --- /dev/null
>> +++ b/src/gallium/drivers/renderonly/renderonly_resource.c
> [snip]
>> +static bool resource_import_scanout(struct renderonly_screen *screen,
>> +                    struct renderonly_resource *resource,
>> +                    const struct pipe_resource *template)
>> +{
>> +       struct winsys_handle handle;
>> +       boolean status;
>> +       int fd, err;
>> +
>> +       resource->gpu = screen->gpu->resource_create(screen->gpu,
>> +                                                            template);
>> +       if (!resource->gpu)
>> +               return false;
>> +
>> +       memset(&handle, 0, sizeof(handle));
>> +       handle.type = DRM_API_HANDLE_TYPE_FD;
>> +
>> +       status = screen->gpu->resource_get_handle(screen->gpu,
>> +                                                         resource->gpu,
>> +                                                         &handle);
>> +       if (!status)
> We're missing the cleanup in the error paths in this function.
>

Correct. Will fix it.

>> +               return false;
>> +
>> +       resource->stride = handle.stride;
>> +       fd = handle.handle;
>> +
>> +       err = drmPrimeFDToHandle(screen->fd, fd, &resource->handle);
>> +       if (err < 0) {
>> +               fprintf(stderr, "drmPrimeFDToHandle() failed: %s\n",
>> +                       strerror(errno));
>> +               close(fd);
> Not 100% sure that we can/should close the fd, here and below.
>

Me neither. I will have a look at the docs.

>> +               return false;
>> +       }
>> +
>> +       close(fd);
>
> [snip]
>> +static bool resource_dumb(struct renderonly_screen *screen,
>> +                    struct renderonly_resource *resource,
>> +                    const struct pipe_resource *template)
>> +{
>> +       struct drm_mode_create_dumb create_dumb = { 0 };
>> +       struct winsys_handle handle;
>> +       int prime_fd, err;
>> +
>> +       /* create dumb buffer at scanout GPU */
> Use memset(&create_dumb...) like the rest of the patch ?
>

Yes - that makes it more consistent.

>> +       create_dumb.width = template->width0;
>> +       create_dumb.height = template->height0;
>> +       create_dumb.bpp = 32;
>> +       create_dumb.flags = 0;
>> +       create_dumb.pitch = 0;
>> +       create_dumb.size = 0;
>> +       create_dumb.handle = 0;
>> +
>> +       err = ioctl(screen->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
> While I'm not objecting (esp. considering your usecase) there has been
> concerns about doing any form of accelerated rendering + dumb fb. I'd
> suspect that the relevant drivers and/or drm core might need to be
> laxed for this to work ?

Whats the meaning of laxed? Can tell me more about that concerns?

>
>> +       if (err < 0) {
>> +               fprintf(stderr, "DRM_IOCTL_MODE_CREATE_DUMB failed: %s\n",
>> +                       strerror(errno));
>> +               return false;
>> +       }
>> +
>> +       resource->handle = create_dumb.handle;
>> +       resource->stride = create_dumb.pitch;
>> +
>> +       /* create resource at renderonly GPU */
>> +       resource->gpu = screen->gpu->resource_create(screen->gpu, template);
>> +       if (!resource->gpu)
> Similar to resource_import_scanout() we're leaking various bits on error.
>

Will have a look at it.

> [snip]
>> +struct pipe_resource *
>> +renderonly_resource_create(struct pipe_screen *pscreen,
>> +                     const struct pipe_resource *template)
>> +{
>
> [snip]
>> +destroy:
>> +       if (resource->gpu)
>> +               screen->gpu->resource_destroy(screen->gpu, resource->gpu);
> We don't directly create the resource* so we shouldn't destroy it.
>

Ok.

> [snip]
>> --- /dev/null
>> +++ b/src/gallium/drivers/renderonly/renderonly_screen.c
> [snip]
>> +static const char *
>> +renderonly_get_name(struct pipe_screen *pscreen)
>> +{
>> +       static char buffer[256];
>> +       struct renderonly_screen *screen = to_renderonly_screen(pscreen);
>> +
>> +       util_snprintf(buffer, sizeof(buffer), "%s-%s",
>> +                       drmGetDeviceNameFromFd(screen->fd),
> drmGetDeviceNameFromFd() might not be the exact thing we want here,
> but we can lots of time until the feature freeze to tweak it.
>

Fine.

>> +                       screen->gpu->get_name(screen->gpu));
>> +       return buffer;
>> +}
>> +
>> +static const char *
>> +renderonly_get_vendor(struct pipe_screen *pscreen)
>> +{
>> +       return "renderonly";
> This also looks a bit strange. Again can be fixed later on.
>

We could return a mixture of scanout and renderonly driver vendor.

> [snip]
>> +static int renderonly_open_render_node(int fd)
>> +{
>> +       return open("/dev/dri/renderD128", O_RDWR);
> Doesn't drmGetRenderDeviceNameFromFd() provide the correct string here
> ? Might want to use loader_open_device() over open() as it also
> handles O_CLOEXEC.
>
I will have a look at it.

Thanks
--
Christian Gmeiner, MSc

https://soundcloud.com/christian-gmeiner


More information about the mesa-dev mailing list