[Mesa-dev] [android-x86-devel] [RFC 7/7] android: support swrast
Emil Velikov
emil.l.velikov at gmail.com
Fri Apr 29 11:00:59 UTC 2016
On 28 April 2016 at 08:35, Chih-Wei Huang <cwhuang at android-x86.org> wrote:
> From: WuZhen <wuzhen at jidemail.com>
>
> System boots up with gles_mesa/softpipe/llvmpipe.
>
> NO_REF_TASK
> tested: local run
>
> Change-Id: I629ed0ca9fad12e32270eb8e8bfa9f7681b68474
> Signed-off-by: Chih-Wei Huang <cwhuang at linux.org.tw>
> ---
> Android.mk | 2 +-
> include/GL/internal/dri_interface.h | 9 +-
> src/egl/Android.mk | 1 +
> src/egl/drivers/dri2/egl_dri2.c | 1 +
> src/egl/drivers/dri2/platform_android.c | 386 ++++++++++++++++++++++++-
> src/gallium/Android.mk | 2 +-
> src/gallium/drivers/llvmpipe/Android.mk | 37 +++
> src/gallium/include/state_tracker/drm_driver.h | 10 +-
> src/gallium/state_trackers/dri/dri2.c | 6 +-
> src/gallium/state_trackers/dri/drisw.c | 46 +++
> src/gallium/targets/dri/Android.mk | 8 +-
> src/gallium/winsys/sw/dri/Android.mk | 2 +
> src/gallium/winsys/sw/dri/dri_sw_winsys.c | 64 ++++
> src/mesa/drivers/dri/common/dri_util.c | 4 +-
> src/mesa/drivers/dri/common/dri_util.h | 2 +-
> 15 files changed, 555 insertions(+), 25 deletions(-)
> create mode 100644 src/gallium/drivers/llvmpipe/Android.mk
>
How to split things:
- introduce the DRI extension - elaborate thoroughly why it's needed,
how it will be used.
- extend the gallium interface - as above, one should elaborate why/how
- extend/fix the winsys
- extend/fix the st (could be squashed with the winsys patch)
- wire up the DRI interface (EGL loader, dri/common)
- softpipe should work now, thus we can add the llvmpipe build
High level suggestions
- Code from src/egl cannot know about src/gallium and vice-versa.
- Gallium can be (is) aware of src/mesa/drivers/dri/common (and
include/GL) but the other way around
We have some exceptions for the above but those are unrelated.
A collection of suggestions follows inline.
> --- a/include/GL/internal/dri_interface.h
> +++ b/include/GL/internal/dri_interface.h
> @@ -62,6 +62,7 @@ typedef struct __DRIdrawableRec __DRIdrawable;
> typedef struct __DRIconfigRec __DRIconfig;
> typedef struct __DRIframebufferRec __DRIframebuffer;
> typedef struct __DRIversionRec __DRIversion;
> +typedef struct __DRIimageRec __DRIimage;
>
How old of a mesa are you using ? Mesa 11.0 series already has this -
did you deliberately/unintentionally duplicate it ?
> --- a/src/egl/drivers/dri2/platform_android.c
> +++ b/src/egl/drivers/dri2/platform_android.c
> @@ -37,10 +37,11 @@
> #include "loader.h"
> #include "egl_dri2.h"
> #include "egl_dri2_fallbacks.h"
> +#include "state_tracker/drm_driver.h"
As mentioned above - you cannot do this.
> #include "gralloc_drm.h"
> #include "gralloc_drm_handle.h"
>
> -static int
> +static inline int
> get_format_bpp(int native)
Don't bother with such changes. Compiler should be smart enough to
figure it out.
> +static void
> +swrastPutImage2(__DRIdrawable * draw, int op,
> + int x, int y, int w, int h, int stride,
> + char *data, void *loaderPrivate)
> +{
> + struct dri2_egl_surface *dri2_surf = loaderPrivate;
> + char *dstPtr, *srcPtr;
> + size_t BPerPixel, dstStride, copyWidth, xOffset;
> +
Wrong naming scheme/format. Follow the surrounding one. Same goes for GetImage
> +// _eglLog(_EGL_WARNING, "calling swrastPutImage with draw=%p, private=%p, x=%d, y=%d, w=%d, h=%d",
> +// draw, loaderPrivate, x, y, w, h);
> +
Either uncomment this or nuke it.
> + if (swrastUpdateBuffer(dri2_surf)) {
> + return;
> + }
Don't bother with putting {} if there's a single line within the
conditional. Same goes throughout the patch.
> +
> + BPerPixel = get_format_bpp(dri2_surf->buffer->format);
> + dstStride = BPerPixel * dri2_surf->buffer->stride;
> + copyWidth = BPerPixel * w;
> + xOffset = BPerPixel * x;
> +
> + /* drivers expect we do these checks (and some rely on it) */
> + if (copyWidth > dstStride - xOffset)
> + copyWidth = dstStride - xOffset;
> + if (h > dri2_surf->base.Height - y)
> + h = dri2_surf->base.Height - y;
> +
> + if (gr_module->lock(gr_module, dri2_surf->buffer->handle, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
Please wrap lines up-to ~80 chars. Same goes in other places through the patch.
> + 0, 0, dri2_surf->buffer->width, dri2_surf->buffer->height, (void**)&dstPtr)) {
> + _eglLog(_EGL_WARNING, "can not lock window buffer");
> + return;
> + }
> +
> + dstPtr += y * dstStride + xOffset;
> + srcPtr = data;
> +
> + for (; h>0; h--) {
Space between "(" and ";" and around ether side of ">". GetImage would
need this as well.
> +static _EGLImage *
> +swrast_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
> + _EGLContext *ctx, EGLenum target,
> + EGLClientBuffer buffer, const EGLint *attr_list)
> +{
> + switch (target) {
> + case EGL_NATIVE_BUFFER_ANDROID:
> + return swrast_create_image_android_native_buffer(disp, ctx,
> + (struct ANativeWindowBuffer *) buffer);
Nit: Change the function definition to use buffer of type
EGLClientBuffer and drop the cast here ?
> + default:
> + return dri2_fallback_create_image_khr(drv, disp, ctx, target, buffer, attr_list);
> + }
> +}
> +
> static int
> -droid_open_device(void)
> +load_gralloc(void)
This and is_drm_gralloc() could be prefixed with droid_ to indicate
that they're diving into android specifics.
> {
> const hw_module_t *mod;
> - int fd = -1, err;
> + int err;
>
> err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod);
> if (!err) {
> - const gralloc_module_t *gr = (gralloc_module_t *) mod;
> -
> - err = -EINVAL;
> - if (gr->perform)
> - err = gr->perform(gr, GRALLOC_MODULE_PERFORM_GET_DRM_FD, &fd);
> + gr_module = (gralloc_module_t *) mod;
> + } else {
> + _eglLog(_EGL_WARNING, "fail to load gralloc");
> }
> + return err;
> +}
> +
> +static int
> +is_drm_gralloc(void)
> +{
> + /* need a cleaner way to distinguish drm_gralloc and gralloc.default */
Use XXX or TODO. On the topic in question - can one add/use different
'magic' and detect things based on that ?
> @@ -882,3 +1130,115 @@ cleanup_display:
>
> return _eglError(EGL_NOT_INITIALIZED, err);
> }
> +
> +/* differs with droid_display_vtbl in create_image, swap_buffers */
Does this add much value ?
> +static struct dri2_egl_display_vtbl swrast_display_vtbl = {
Make it a constant ?
> + .authenticate = NULL,
> + .create_window_surface = droid_create_window_surface,
> + .create_pixmap_surface = dri2_fallback_create_pixmap_surface,
> + .create_pbuffer_surface = droid_create_pbuffer_surface,
> + .destroy_surface = droid_destroy_surface,
> + .create_image = swrast_create_image_khr,
> + .swap_interval = dri2_fallback_swap_interval,
> + .swap_buffers = swrast_swap_buffers,
> + .swap_buffers_with_damage = dri2_fallback_swap_buffers_with_damage,
> + .swap_buffers_region = dri2_fallback_swap_buffers_region,
> + .post_sub_buffer = dri2_fallback_post_sub_buffer,
> + .copy_buffers = dri2_fallback_copy_buffers,
> + .query_buffer_age = dri2_fallback_query_buffer_age,
> + .create_wayland_buffer_from_image = dri2_fallback_create_wayland_buffer_from_image,
> + .get_sync_values = dri2_fallback_get_sync_values,
> + .get_dri_drawable = dri2_surface_get_dri_drawable,
> +};
> +
> +static EGLBoolean
> +dri2_initialize_android_swrast(_EGLDriver *drv, _EGLDisplay *dpy)
> +{
> +
> + dri2_dpy->extensions[0] = &dri2_dpy->swrast_loader_extension.base;
> + dri2_dpy->extensions[1] = &image_lookup_extension.base;
> + dri2_dpy->extensions[2] = NULL;
> +
Just throw these to a static const table and have dri2_dpy->extensions
point to it ?
> + if (!dri2_create_screen(dpy)) {
> + err = "DRISW: failed to create screen";
> + goto cleanup_driver;
> + }
> +
> + if (!droid_add_configs_for_visuals(drv, dpy)) {
> + err = "DRISW: failed to add configs";
> + goto cleanup_screen;
> + }
> +
> + dpy->Extensions.ANDROID_framebuffer_target = EGL_TRUE;
> + dpy->Extensions.ANDROID_image_native_buffer = EGL_TRUE;
> + dpy->Extensions.ANDROID_recordable = EGL_TRUE;
> + dpy->Extensions.KHR_image_base = EGL_TRUE;
> +
Move these into a helper/static function. Otherwise we'll update one
copy but forget about the other.
> + /* Fill vtbl last to prevent accidentally calling virtual function during
> + * initialization.
> + */
> + dri2_dpy->vtbl = &swrast_display_vtbl;
> +
> + return EGL_TRUE;
> +
> +cleanup_screen:
> + dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
> +cleanup_driver:
> + dlclose(dri2_dpy->driver);
> +cleanup_driver_name:
> + free(dri2_dpy->driver_name);
> + free(dri2_dpy);
> +
> + return _eglError(EGL_NOT_INITIALIZED, err);
> +}
> +
> +EGLBoolean
> +dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *dpy)
> +{
> + EGLBoolean initialized = EGL_TRUE;
> +
> + if (load_gralloc()) {
> + return EGL_FALSE;
> + }
> +
> + int droid_hw_accel = (getenv("LIBGL_ALWAYS_SOFTWARE") == NULL) && is_drm_gralloc();
> +
> + if (droid_hw_accel) {
> + if (!dri2_initialize_android_drm(drv, dpy)) {
> + initialized = dri2_initialize_android_swrast(drv, dpy);
> + if (initialized) {
> + _eglLog(_EGL_INFO, "Android: Fallback to software renderer");
_EGL_WARN ?
> --- a/src/gallium/state_trackers/dri/dri2.c
> +++ b/src/gallium/state_trackers/dri/dri2.c
> @@ -690,7 +690,7 @@ dri2_update_tex_buffer(struct dri_drawable *drawable,
> /* no-op */
> }
>
> -static __DRIimage *
> +__DRIimage *
> dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
> {
> const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image;
> @@ -705,7 +705,7 @@ dri2_lookup_egl_image(struct dri_screen *screen, void *handle)
> return img;
> }
>
> -static __DRIimage *
> +__DRIimage *
Making these non-static could/should be a preparatory commit.
> --- a/src/gallium/state_trackers/dri/drisw.c
> +++ b/src/gallium/state_trackers/dri/drisw.c
> @@ -407,6 +450,9 @@ drisw_init_screen(__DRIscreen * sPriv)
> if (!configs)
> goto fail;
>
> + screen->lookup_egl_image = dri2_lookup_egl_image;
> + driSWRastExtension.createImageFromWinsys = dri2_create_image_from_winsys;
> +
You can add this vfunc only if you bump the version _here_
> return configs;
> fail:
> dri_destroy_screen_helper(screen);
> diff --git a/src/gallium/targets/dri/Android.mk b/src/gallium/targets/dri/Android.mk
> index a14d449..0e93364 100644
> --- a/src/gallium/targets/dri/Android.mk
> +++ b/src/gallium/targets/dri/Android.mk
> ifneq ($(filter swrast,$(MESA_GPU_DRIVERS)),)
> -gallium_DRIVERS += libmesa_pipe_softpipe libmesa_winsys_sw_dri
> -LOCAL_CFLAGS += -DGALLIUM_SOFTPIPE
> +gallium_DRIVERS += libmesa_pipe_llvmpipe libmesa_pipe_softpipe libmesa_winsys_sw_dri
> +LOCAL_CFLAGS += -DGALLIUM_LLVMPIPE -DGALLIUM_SOFTPIPE
> +LOCAL_SHARED_LIBRARIES += libLLVM
In general one would either a) introduce new variable for
MESA_GPU_DRIVERS - llvmpipe or b) optionally build llvmpipe when LLVM
is enabled.
The proposed approach "always force llvm with swrast driver" feels
quite strange.
> endif
> ifneq ($(filter vc4,$(MESA_GPU_DRIVERS)),)
> LOCAL_CFLAGS += -DGALLIUM_VC4
> @@ -138,5 +140,7 @@ LOCAL_STATIC_LIBRARIES += \
> LOCAL_LDLIBS += $(if $(filter true,$(MESA_LOLLIPOP_BUILD)),-lgcc)
> endif
>
> +LOCAL_ADDITION_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
> +
What does this one do, where/why do we need it ?
> --- a/src/mesa/drivers/dri/common/dri_util.c
> +++ b/src/mesa/drivers/dri/common/dri_util.c
> @@ -760,8 +760,8 @@ const __DRIdri2Extension driDRI2Extension = {
> .createNewScreen2 = driCreateNewScreen2,
> };
>
> -const __DRIswrastExtension driSWRastExtension = {
> - .base = { __DRI_SWRAST, 4 },
> +__DRIswrastExtension driSWRastExtension = {
> + .base = { __DRI_SWRAST, 5 },
>
As mentioned above - you cannot change the compile time version (here)
while adding the new function ptr at run time (in drisw_init_screen).
Thanks
Emil
More information about the mesa-dev
mailing list