[Mesa-dev] [PATCH 1/3] gallium: add renderonly library
Christian Gmeiner
christian.gmeiner at gmail.com
Mon Dec 19 19:54:04 UTC 2016
Hi Thierry,
2016-12-19 14:08 GMT+01:00 Thierry Reding <thierry.reding at gmail.com>:
> On Wed, Nov 30, 2016 at 02:44:34PM +0100, Christian Gmeiner wrote:
>> This a very lightweight library to add basic support for
>> renderonly GPUs. It does all the magic regarding in/exporting
>> buffers etc. This library will likely break android support and
>> hopefully will get replaced with a better solution based on gbm2.
>>
>> Signed-off-by: Christian Gmeiner <christian.gmeiner at gmail.com>
>> ---
>> src/gallium/Automake.inc | 5 +
>> src/gallium/auxiliary/Makefile.am | 10 ++
>> src/gallium/auxiliary/Makefile.sources | 4 +
>> src/gallium/auxiliary/renderonly/renderonly.c | 199 ++++++++++++++++++++++++++
>> src/gallium/auxiliary/renderonly/renderonly.h | 81 +++++++++++
>> 5 files changed, 299 insertions(+)
>> create mode 100644 src/gallium/auxiliary/renderonly/renderonly.c
>> create mode 100644 src/gallium/auxiliary/renderonly/renderonly.h
>
> Hi Christian,
>
> sorry for being late to the party. I only ran across this by accident.
> Would you mind keeping me in Cc for subsequent versions of this? It's
> been more than two years since I wrote the original proposal for this,
> but I'm still interested in seeing a solution emerge.
>
Sure will add you to CC list. Btw. your timing could not be better I
wanted to send out
v2 today. But I will hold it back and incooperate your feedback.
> Anyway, thanks for picking this up.
>
> From a diff point of view this is certainly much more terse than the
> original proposal. I find it slightly unfortunate that the drivers for
> the render GPU have to be changed. But it's hard to argue with the
> reduction in size.
>
> I still think that Tegra will eventually require more than the stub that
> you have in this series because the same device that exposes the scanout
> engine also contains units that can do video compositing, decoding and
> encoding. There's in fact recently been discussions on how best to
> provide that functionality and Mesa looks like the best long-term target
> currently. Anyway, that's a bridge I think we can cross when we get
> there, this concept looks fine to get started.
>
>> diff --git a/src/gallium/Automake.inc b/src/gallium/Automake.inc
>> index 6fe2e22..6aadcb9 100644
>> --- a/src/gallium/Automake.inc
>> +++ b/src/gallium/Automake.inc
>> @@ -50,6 +50,11 @@ GALLIUM_COMMON_LIB_DEPS = \
>> $(PTHREAD_LIBS) \
>> $(DLOPEN_LIBS)
>>
>> +if HAVE_LIBDRM
>> +GALLIUM_COMMON_LIB_DEPS += \
>> + $(LIBDRM_LIBS)
>> +endif
>
> Nit: Is the conditional necessary here? LIBDRM_LIBS would be empty if
> libdrm wasn't found, right? So no harm in just appending it to the
> GALLIUM_COMMON_LIB_DEPS variable unconditonally?
>
Done.
>> GALLIUM_WINSYS_CFLAGS = \
>> -I$(top_srcdir)/src \
>> -I$(top_srcdir)/include \
>> diff --git a/src/gallium/auxiliary/Makefile.am b/src/gallium/auxiliary/Makefile.am
>> index 4a4a4fb..6b63cf1 100644
>> --- a/src/gallium/auxiliary/Makefile.am
>> +++ b/src/gallium/auxiliary/Makefile.am
>> @@ -20,6 +20,16 @@ libgallium_la_SOURCES = \
>> $(NIR_SOURCES) \
>> $(GENERATED_SOURCES)
>>
>> +if HAVE_LIBDRM
>> +
>> +AM_CFLAGS += \
>> + $(LIBDRM_CFLAGS)
>
> Same here.
I just redone what other have done in that file. There are some if's
in that file and I am unsure
what to do here.
>
>> diff --git a/src/gallium/auxiliary/Makefile.sources b/src/gallium/auxiliary/Makefile.sources
>> index 5d4fe30..8d3e4a9 100644
>> --- a/src/gallium/auxiliary/Makefile.sources
>> +++ b/src/gallium/auxiliary/Makefile.sources
>> @@ -435,3 +435,7 @@ GALLIVM_SOURCES := \
>> draw/draw_llvm_sample.c \
>> draw/draw_pt_fetch_shade_pipeline_llvm.c \
>> draw/draw_vs_llvm.c
>> +
>> +RENDERONLY_SOURCES := \
>> + renderonly/renderonly.c \
>> + renderonly/renderonly.h
>> diff --git a/src/gallium/auxiliary/renderonly/renderonly.c b/src/gallium/auxiliary/renderonly/renderonly.c
>> new file mode 100644
>> index 0000000..c4ea784
>> --- /dev/null
>> +++ b/src/gallium/auxiliary/renderonly/renderonly.c
>> @@ -0,0 +1,199 @@
>> +/*
>> + * Copyright (C) 2016 Christian Gmeiner <christian.gmeiner at gmail.com>
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a
>> + * copy of this software and associated documentation files (the "Software"),
>> + * to deal in the Software without restriction, including without limitation
>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
>> + * 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, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
>> + * SOFTWARE.
>> + *
>> + * Authors:
>> + * Christian Gmeiner <christian.gmeiner at gmail.com>
>> + */
>> +
>> +#include "renderonly/renderonly.h"
>
> This include is oddly placed. Should it not go below all other includes?
>
I think thats a matter of style but I can puit it above #include
"state_tracker/drm_driver.h"
>> +
>> +#include <errno.h>
>> +#include <fcntl.h>
>> +#include <stdio.h>
>> +#include <sys/ioctl.h>
>> +#include <xf86drm.h>
>> +
>> +#include "state_tracker/drm_driver.h"
>> +#include "pipe/p_screen.h"
>> +#include "util/u_memory.h"
>> +
>> +struct pipe_screen *
>> +renderonly_screen_create(int fd, const struct renderonly_ops *ops, void *priv)
>
> This is slightly nit-picky, but I found it confusing when first reading
> through the patches: I know this started out as an effort to support the
> various render-only devices out there, but what you're creating here is
> really an abstraction for the scanout engine. Reading renderonly_* the
> first thing I think of is that this creates a render-only device, where
> in fact is creates the scanout engine.
>
> Perhaps renaming this to struct scanout, struct scanout_engine or any
> other number of possibilities would remove that confusion.
>
In my current version I have only one struct left:
struct renderonly {
int (*tiling)(int fd, uint32_t handle); /**< for !intermediate_rendering */
bool intermediate_rendering;
int kms_fd;
int gpu_fd;
};
And here is how the only function in imx-drm winsys looks like:
struct pipe_screen *imx_drm_screen_create(int fd)
{
struct renderonly ro = {
.intermediate_rendering = true,
.kms_fd = fd,
.gpu_fd = open("/dev/dri/renderD128", O_RDWR | O_CLOEXEC)
};
if (ro.gpu_fd < 0)
return NULL;
struct pipe_screen *screen = etna_drm_screen_create_renderonly(&ro);
if (!screen)
close(ro.gpu_fd);
return screen;
}
So everything got more explicit regarding file handles and the struct represents
the combination of the kms and a gpu device now. I am not sure if the rename
is still needed but if it is maybe something like renderonly_ctx would work.
>> +{
>> + struct renderonly *ro;
>> +
>> + ro = CALLOC_STRUCT(renderonly);
>> + if (!ro)
>> + return NULL;
>> +
>> + ro->kms_fd = fd;
>
> The kms_ prefix seems rather redundant to me, given that struct
> renderonly represents the KMS device.
>
Was true for V1 but in V2 everything looks quite different.
>> + ro->ops = ops;
>> + ro->priv = priv;
>> +
>> + ro->screen = ops->create(ro);
>
> It's somewhat odd that drivers need to jump through this hoop in order
> to create their screens. I think it would be easier if they just
> embedded the struct renderonly and initialized it in their create
> function.
>
> I think that's probably what Nicolai and Emil were saying as well.
Yeah.. with V2 everything feels much easier to understand and cleaner.
>
>> + if (!ro->screen)
>> + goto cleanup;
>> +
>> + return ro->screen;
>> +
>> +cleanup:
>> + FREE(ro);
>> +
>> + return NULL;
>> +}
>> +
>> +static bool
>> +use_kms_bumb_buffer(struct renderonly_scanout *scanout,
>
> You probably meant "dumb" here. Somehow you managed to get it right in
> the variables, but the function name and the callsite consistently have
> the same typo. =)
>
Upps.. :)
>> + struct pipe_resource *rsc, struct renderonly *ro)
>> +{
>> + struct winsys_handle handle;
>> + int prime_fd, err;
>> + struct drm_mode_create_dumb create_dumb = {
>> + .width = rsc->width0,
>> + .height = rsc->height0,
>> + .bpp = 32,
>
> This seems like maybe too strong an assumption. Or at the very least a
> waste of memory. What if somebody wanted to use 16- or 24-bit buffers?
>
Good point... have an answer for this later in the mail.
>> +static bool
>> +import_gpu_scanout(struct renderonly_scanout *scanout,
>> + struct pipe_resource *rsc, struct renderonly *ro)
>> +{
>> + struct pipe_screen *screen = ro->screen;
>> + boolean status;
>> + int fd, err;
>> + struct winsys_handle handle = {
>> + .type = DRM_API_HANDLE_TYPE_FD
>> + };
>> +
>> + status = screen->resource_get_handle(screen, NULL, rsc, &handle,
>> + PIPE_HANDLE_USAGE_READ_WRITE);
>> + if (!status)
>> + return false;
>> +
>> + scanout->stride = handle.stride;
>> + fd = handle.handle;
>> +
>> + err = drmPrimeFDToHandle(ro->kms_fd, fd, &scanout->handle);
>> + close(fd);
>> +
>> + if (err < 0) {
>> + fprintf(stderr, "drmPrimeFDToHandle() failed: %s\n", strerror(errno));
>> + return false;
>> + }
>> +
>> + if (ro->ops->tiling) {
>
> tiling is maybe not the best name for this, since arguable the scanout
> driver might want to do any number of other things while importing.
> Perhaps ->import() would be generic enough?
>
import() sounds fine to me but maybe we can drop it.
>> + err = ro->ops->tiling(ro->kms_fd, scanout->handle);
>> + if (err < 0) {
>> + fprintf(stderr, "failed to set tiling parameters: %s\n", strerror(errno));
>> + close(scanout->handle);
>
> I don't think scanout->handle is something you should be passing to
> close().
>
Yeah.. looks you are right.. fill fix that in V2.
>> + return false;
>> + }
>> + }
>> +
>> + return true;
>> +}
>> +
>> +struct renderonly_scanout *
>> +renderonly_scanout_for_resource(struct pipe_resource *rsc, struct renderonly *ro)
>> +{
>> + struct renderonly_scanout *scanout;
>> + bool ret;
>> +
>> + scanout = CALLOC_STRUCT(renderonly_scanout);
>> + if (!scanout)
>> + return NULL;
>> +
>> + if (ro->ops->intermediate_rendering)
>> + ret = use_kms_bumb_buffer(scanout, rsc, ro);
>> + else
>> + ret = import_gpu_scanout(scanout, rsc, ro);
>
> Given my kernel background I've grown allergic to this kind of
> construct. What you're creating here is a midlayer that's very likely to
> cause headaches down the road. I think a better alternative would be to
> add a callback to the struct renderonly_ops that drivers have to set to
> whatever the implementation is that they want.
This is a very good point and I thought about it some days ago.
> If you want to provide standard helpers, that's fine. Turn both the
> use_kms_bumb_buffer() and import_gpu_scanout() functions into public
> functions that drivers can reference. Then drivers can simply assign
> them to the new operation, or implement their own if they find that the
> defaults aren't flexible enough.
>
So the struct renderonly could look like:
struct renderonly {
struct renderonly_scanout *(*create_for_resource)(struct pipe_resource *rsc);
int kms_fd;
int gpu_fd;
};
Now the kms winsys part can define what needs to be done in a generic way. I
am not sure if it would make lot of sense to provide a use_kms_bumb_buffer()
or import_gpu_scanout() public functions at all as every driver may need a small
variation if them. This also solves the 16 vs. 24 vs 32 bit buffer
problem by pushing
it directly to the kms winsys part - nice!
> On of the problem, the most immediate in this case, with this kind of
> midlayer is that if intermediate_rendering == {false,true} is not enough
> for a given use-case, we end up having to add yet another flag that
> specifies behaviour.
>
Thanks for your review!
greets
--
Christian Gmeiner, MSc
https://soundcloud.com/christian-gmeiner
More information about the mesa-dev
mailing list