+ Karl 2017-05-01 17:02 GMT+02:00 Mauro Rossi <issor.or...@gmail.com>:
> > > 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_b >> uffer_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