2017-01-06 18:35 GMT+01:00 Wu Zhen <wuz...@jidemail.com>: > From: WuZhen <wuz...@jidemail.com> > > this commit enable software rendering on android with llvmpipe. > the system boots fine antutu 3D benchmark is passing > > this commit incorporates some further work done by: > Paulo Sergio Travaglia <pstg...@gmail.com> > Mauro Rossi <issor.or...@gmail.com> > > Change-Id: Ibe0114333a278fd5e64632ac8c17cffde7c9b359 > Reviewed-by: Mauro Rossi <issor.or...@gmail.com> > Reviewed-by: Chih-Wei Huang <cwhu...@linux.org.tw> > --- > src/egl/Android.mk | 1 + > src/egl/drivers/dri2/egl_dri2.c | 1 + > src/egl/drivers/dri2/platform_android.c | 389 > +++++++++++++++++++++++++++++++- > 3 files changed, 386 insertions(+), 5 deletions(-) > > diff --git a/src/egl/Android.mk b/src/egl/Android.mk > index bfd56a744d..d63e71da92 100644 > --- a/src/egl/Android.mk > +++ b/src/egl/Android.mk > @@ -46,6 +46,7 @@ LOCAL_CFLAGS := \ > LOCAL_C_INCLUDES := \ > $(MESA_TOP)/src/egl/main \ > $(MESA_TOP)/src/egl/drivers/dri2 \ > + $(MESA_TOP)/src/gallium/include > > LOCAL_STATIC_LIBRARIES := \ > libmesa_loader > diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_ > dri2.c > index 52fbdff0b1..bdb3119496 100644 > --- a/src/egl/drivers/dri2/egl_dri2.c > +++ b/src/egl/drivers/dri2/egl_dri2.c > @@ -402,6 +402,7 @@ static const struct dri2_extension_match > swrast_driver_extensions[] = { > > static const struct dri2_extension_match swrast_core_extensions[] = { > { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, > + { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) }, > { NULL, 0, 0 } > }; > > diff --git a/src/egl/drivers/dri2/platform_android.c > b/src/egl/drivers/dri2/platform_android.c > index 1c880f934a..61c0aa4818 100644 > --- a/src/egl/drivers/dri2/platform_android.c > +++ b/src/egl/drivers/dri2/platform_android.c > @@ -40,6 +40,7 @@ > #include "loader.h" > #include "egl_dri2.h" > #include "egl_dri2_fallbacks.h" > +#include "state_tracker/drm_driver.h" > #include "gralloc_drm.h" > > #define ALIGN(val, align) (((val) + (align) - 1) & ~((align) - 1)) > @@ -157,6 +158,8 @@ get_native_buffer_name(struct ANativeWindowBuffer *buf) > return gralloc_drm_get_gem_handle(buf->handle); > } > > +static const gralloc_module_t *gr_module = NULL; > + > static EGLBoolean > droid_window_dequeue_buffer(struct dri2_egl_surface *dri2_surf) > { > @@ -338,9 +341,14 @@ droid_create_surface(_EGLDriver *drv, _EGLDisplay > *disp, EGLint type, > if (!config) > goto cleanup_surface; > > - dri2_surf->dri_drawable = > - (*dri2_dpy->dri2->createNewDrawable)(dri2_dpy->dri_screen, config, > - dri2_surf); > + if (dri2_dpy->dri2) { > + dri2_surf->dri_drawable = > + dri2_dpy->dri2->createNewDrawable(dri2_dpy->dri_screen, config, > dri2_surf); > + } else { > + dri2_surf->dri_drawable = > + dri2_dpy->swrast->createNewDrawable(dri2_dpy->dri_screen, > config, dri2_surf); > + } > + > if (dri2_surf->dri_drawable == NULL) { > _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); > goto cleanup_surface; > @@ -980,6 +988,259 @@ droid_add_configs_for_visuals(_EGLDriver *drv, > _EGLDisplay *dpy) > return (count != 0); > } > > +static int swrastUpdateBuffer(struct dri2_egl_surface *dri2_surf) > +{ > + if (dri2_surf->base.Type == EGL_WINDOW_BIT) { > + if (!dri2_surf->buffer && !droid_window_dequeue_buffer(dri2_surf)) > { > + _eglLog(_EGL_WARNING, "failed to dequeue buffer for window"); > + return 1; > + } > + dri2_surf->base.Width = dri2_surf->buffer->width; > + dri2_surf->base.Height = dri2_surf->buffer->height; > + } > + return 0; > +} > + > +static void > +swrastGetDrawableInfo(__DRIdrawable * draw, > + int *x, int *y, int *w, int *h, > + void *loaderPrivate) > +{ > + struct dri2_egl_surface *dri2_surf = loaderPrivate; > + > + swrastUpdateBuffer(dri2_surf); > + > + *x = 0; > + *y = 0; > + *w = dri2_surf->base.Width; > + *h = dri2_surf->base.Height; > +} > + > +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; > + struct _EGLDisplay *egl_dpy = dri2_surf->base.Resource.Display; > + char *dstPtr, *srcPtr; > + size_t BPerPixel, dstStride, copyWidth, xOffset; > + > + if (swrastUpdateBuffer(dri2_surf)) { > + return; > + } > + > + 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, > + 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; > + > + if (xOffset == 0 && copyWidth == stride && copyWidth == dstStride) { > + memcpy(dstPtr, srcPtr, copyWidth * h); > + } else { > + for (; h>0; h--) { > + memcpy(dstPtr, srcPtr, copyWidth); > + srcPtr += stride; > + dstPtr += dstStride; > + } > + } > + > + if (gr_module->unlock(gr_module, dri2_surf->buffer->handle)) { > + _eglLog(_EGL_WARNING, "unlock buffer failed"); > + } > + > + droid_window_enqueue_buffer(egl_dpy, dri2_surf); > +} > + > +static void > +swrastPutImage(__DRIdrawable * draw, int op, > + int x, int y, int w, int h, > + char *data, void *loaderPrivate) > +{ > + struct dri2_egl_surface *dri2_surf = loaderPrivate; > + int stride; > + > + if (swrastUpdateBuffer(dri2_surf)) { > + return; > + } > + > + stride = get_format_bpp(dri2_surf->buffer->format) * w; > + swrastPutImage2(draw, op, x, y, w, h, stride, data, loaderPrivate); > +} > + > +static void > +swrastGetImage(__DRIdrawable * read, > + int x, int y, int w, int h, > + char *data, void *loaderPrivate) > +{ > + struct dri2_egl_surface *dri2_surf = loaderPrivate; > + size_t BPerPixel, srcStride, copyWidth, xOffset; > + char *dstPtr, *srcPtr; > + > + _eglLog(_EGL_WARNING, "calling swrastGetImage with read=%p, > private=%p, w=%d, h=%d", read, loaderPrivate, w, h); > + > + if (swrastUpdateBuffer(dri2_surf)) { > + _eglLog(_EGL_WARNING, "swrastGetImage failed data unchanged"); > + return; > + } > + > + BPerPixel = get_format_bpp(dri2_surf->buffer->format); > + srcStride = BPerPixel * dri2_surf->buffer->stride; > + copyWidth = BPerPixel * w; > + xOffset = BPerPixel * x; > + > + if (gr_module->lock(gr_module, dri2_surf->buffer->handle, > GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, > + 0, 0, dri2_surf->buffer->width, > dri2_surf->buffer->height, (void**)&srcPtr)) { > + _eglLog(_EGL_WARNING, "can not lock window buffer"); > + memset(data, 0, copyWidth * h); > + return; > + } > + > + srcPtr += y * srcStride + xOffset; > + dstPtr = data; > + > + if (xOffset == 0 && copyWidth == srcStride) { > + memcpy(dstPtr, srcPtr, copyWidth * h); > + } else { > + for (; h>0; h--) { > + memcpy(dstPtr, srcPtr, copyWidth); > + srcPtr += srcStride; > + dstPtr += copyWidth; > + } > + } > + > + if (gr_module->unlock(gr_module, dri2_surf->buffer->handle)) { > + _eglLog(_EGL_WARNING, "unlock buffer failed"); > + } > +} > + > +static EGLBoolean > +swrast_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface > *draw) > +{ > + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); > + struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); > + > + dri2_dpy->core->swapBuffers(dri2_surf->dri_drawable); > + > + return EGL_TRUE; > +} > + > +static _EGLImage * > +swrast_create_image_android_native_buffer(_EGLDisplay *disp, _EGLContext > *ctx, > + struct ANativeWindowBuffer *buf) > +{ > + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); > + struct dri2_egl_image *dri2_img; > + struct winsys_handle whandle; > + EGLint format; > + > + if (ctx != NULL) { > + /* From the EGL_ANDROID_image_native_buffer spec: > + * > + * * If <target> is EGL_NATIVE_BUFFER_ANDROID and <ctx> is not > + * EGL_NO_CONTEXT, the error EGL_BAD_CONTEXT is generated. > + */ > + _eglError(EGL_BAD_CONTEXT, "eglCreateEGLImageKHR: for " > + "EGL_NATIVE_BUFFER_ANDROID, the context must be " > + "EGL_NO_CONTEXT"); > + return NULL; > + } > + > + if (!buf || buf->common.magic != ANDROID_NATIVE_BUFFER_MAGIC || > + buf->common.version != sizeof(*buf)) { > + _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); > + return NULL; > + } > + > + /* see the table in droid_add_configs_for_visuals */ > + format = get_format(buf->format); > + if (format < 0) > + return NULL; > + > + dri2_img = calloc(1, sizeof(*dri2_img)); > + if (!dri2_img) { > + _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm"); > + return NULL; > + } > + > + if (!_eglInitImage(&dri2_img->base, disp)) { > + free(dri2_img); > + return NULL; > + } > + > + memset(&whandle, 0, sizeof(whandle)); > + whandle.type = DRM_API_HANDLE_TYPE_BUFFER; > + whandle.external_buffer = buf; > + whandle.stride = buf->stride * get_format_bpp(buf->format); > + > + dri2_img->dri_image = > + dri2_dpy->swrast->createImageFromWinsys(dri2_dpy->dri_screen, > + buf->width, > + buf->height, > + format, > + 1, &whandle, > + dri2_img); > + > + if (!dri2_img->dri_image) { > + free(dri2_img); > + _eglError(EGL_BAD_ALLOC, "droid_create_image_mesa_drm"); > + return NULL; > + } > + > + return &dri2_img->base; > +} > + > +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); > + default: > + return dri2_create_image_khr(drv, disp, ctx, target, buffer, > attr_list); > + } > +} > + > +static int > +load_gralloc(void) > +{ > + const hw_module_t *mod; > + int err; > + > + err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &mod); > + if (!err) { > + 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 */ > + return !!gr_module->perform; > +} > + > static int > droid_open_device(struct dri2_egl_display *dri2_dpy) > { > @@ -1064,6 +1325,15 @@ static const __DRIimageLoaderExtension > droid_image_loader_extension = { > .flushFrontBuffer = droid_flush_front_buffer, > }; > > +static const __DRIswrastLoaderExtension droid_swrast_loader_extension = { > + .base = { __DRI_SWRAST_LOADER, 2 }, > + > + .getDrawableInfo = swrastGetDrawableInfo, > + .putImage = swrastPutImage, > + .getImage = swrastGetImage, > + .putImage2 = swrastPutImage2, > +}; > + > static const __DRIextension *droid_dri2_loader_extensions[] = { > &droid_dri2_loader_extension.base, > &image_lookup_extension.base, > @@ -1078,8 +1348,14 @@ static const __DRIextension > *droid_image_loader_extensions[] > = { > NULL, > }; > > -EGLBoolean > -dri2_initialize_android(_EGLDriver *drv, _EGLDisplay *dpy) > +static const __DRIextension *droid_swrast_loader_extensions[] = { > + &droid_swrast_loader_extension.base, > + &image_lookup_extension.base, > + NULL, > +}; > + > +static EGLBoolean > +dri2_initialize_android_drm(_EGLDriver *drv, _EGLDisplay *dpy) > { > struct dri2_egl_display *dri2_dpy; > const char *err; > @@ -1163,3 +1439,106 @@ cleanup_display: > > return _eglError(EGL_NOT_INITIALIZED, err); > } > + > +/* differs with droid_display_vtbl in create_image, swap_buffers */ > +static struct dri2_egl_display_vtbl swrast_display_vtbl = { > + .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) > +{ > + struct dri2_egl_display *dri2_dpy; > + const char *err = ""; > + const hw_module_t *mod; > + > + _eglSetLogProc(droid_log); > + > + loader_set_logger(_eglLog); > + > + dri2_dpy = calloc(1, sizeof(*dri2_dpy)); > + if (!dri2_dpy) > + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); > + > + dpy->DriverData = (void *) dri2_dpy; > + > + dri2_dpy->driver_name = strdup("swrast"); > + if (!dri2_load_driver_swrast(dpy)) { > + err = "DRISW: failed to load swrast driver"; > + goto cleanup_driver_name; > + } > + > + dri2_dpy->loader_extensions = droid_swrast_loader_extensions; > + > + 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; > + > + /* 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"); > + } > + } > + } else { > + initialized = dri2_initialize_android_swrast(drv, dpy); > + } > + > + return initialized; > +} > -- > 2.11.0 >
Hi Emil, Tomasz, Tapani, Karl, comparing this series with other swrast implementations in CrOS, Android-IA, are there other android platform swrast implementations? [Tomasz, Tapani if the question does makes sense] I had checked in other platforms (drm, EGL wayland) but in the past I had found no changes in backbuffer handling/swapBuffer/PutImage2, do you know and could explain me the reason? [Emil if you know, but do not use time if it requires research] I also wanted to check if situation may have changed since January 2017, because of swr and other patches in gallium/swrast submitted to mesa-dev like [1], [2], [3], [4] which seem to tackle with functional needs in backbuffer/image2 and swapbuffer area, even if addressed in winsys instead of EGL platform android. [Karl a brief update will suffice, no hurry] Are there news or consolidated choices about the implementation approach? [` Emil or others] Thanks for sharing you thoughts Mauro [1] https://lists.freedesktop.org/archives/mesa-dev/2017-January/141614.html [2] https://lists.freedesktop.org/archives/mesa-dev/2017-January/141621.html [3] https://lists.freedesktop.org/archives/mesa-dev/2017-January/141616.html [4] https://lists.freedesktop.org/archives/mesa-dev/2017-January/141624.html
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev