diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h index 02888c9aab7..ebf1833b569 100644 --- a/src/egl/drivers/dri2/egl_dri2.h +++ b/src/egl/drivers/dri2/egl_dri2.h @@ -308,6 +308,7 @@ struct dri2_egl_display { /* gralloc vendor usage bit for front rendering */ uint32_t front_rendering_usage; bool has_native_fence_fd; + bool pure_swrast; #endif }; diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c index 017fec6e508..93ffbb05d92 100644 --- a/src/egl/drivers/dri2/platform_android.c +++ b/src/egl/drivers/dri2/platform_android.c @@ -337,7 +337,8 @@ droid_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf, &dri2_surf->base.Height); dri2_surf->gralloc_usage = - strcmp(dri2_dpy->driver_name, "kms_swrast") == 0 + ((strcmp(dri2_dpy->driver_name, "kms_swrast") == 0) || + (strcmp(dri2_dpy->driver_name, "swrast") == 0)) ? GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN : GRALLOC_USAGE_HW_RENDER; @@ -616,6 +617,7 @@ droid_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surface) static EGLBoolean droid_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw) { + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); const bool has_mutable_rb = _eglSurfaceHasMutableRenderBuffer(draw); @@ -645,16 +647,22 @@ droid_swap_buffers(_EGLDisplay *disp, _EGLSurface *draw) dri2_flush_drawable_for_swapbuffers_flags(disp, draw, __DRI2_NOTHROTTLE_SWAPBUFFER); - /* dri2_surf->buffer can be null even when no error has occurred. For - * example, if the user has called no GL rendering commands since the - * previous eglSwapBuffers, then the driver may have not triggered - * a callback to ANativeWindow_dequeueBuffer, in which case - * dri2_surf->buffer remains null. - */ - if (dri2_surf->buffer) - droid_window_enqueue_buffer(disp, dri2_surf); + if (dri2_dpy->pure_swrast) { + driSwapBuffers(dri2_surf->dri_drawable); + if (dri2_surf->buffer) + droid_window_enqueue_buffer(disp, dri2_surf); + } else { + /* dri2_surf->buffer can be null even when no error has occurred. For + * example, if the user has called no GL rendering commands since the + * previous eglSwapBuffers, then the driver may have not triggered + * a callback to ANativeWindow_dequeueBuffer, in which case + * dri2_surf->buffer remains null. + */ + if (dri2_surf->buffer) + droid_window_enqueue_buffer(disp, dri2_surf); - dri_invalidate_drawable(dri2_surf->dri_drawable); + dri_invalidate_drawable(dri2_surf->dri_drawable); + } /* Update the shared buffer mode */ if (has_mutable_rb && @@ -944,6 +952,51 @@ droid_display_shared_buffer(__DRIdrawable *driDrawable, int fence_fd, handle_in_fence_fd(dri2_surf, dri2_surf->dri_image_back); } +static void +droid_swrast_get_drawable_info(__DRIdrawable *drawable, + int *x, int *y, int *width, int *height, + void *loaderPrivate) +{ + struct dri2_egl_surface *dri2_surf = loaderPrivate; + + update_buffers(dri2_surf); + + *x = 0; + *y = 0; + *width = dri2_surf->base.Width; + *height = dri2_surf->base.Height; +} + +static void +droid_swrast_put_image2(__DRIdrawable *draw, int op, int x, int y, int w, + int h, int stride, char *data, void *loaderPrivate) +{ + return; +} + +static void +droid_swrast_put_image(__DRIdrawable *draw, int op, int x, int y, int w, + int h, char *data, void *loaderPrivate) +{ + return; +} + +static void +droid_swrast_get_image(__DRIdrawable *read, int x, int y, int w, int h, + char *data, void *loaderPrivate) +{ + return; +} + +static const __DRIswrastLoaderExtension swrast_loader_extension = { + .base = {__DRI_SWRAST_LOADER, 2}, + + .getDrawableInfo = droid_swrast_get_drawable_info, + .putImage = droid_swrast_put_image, + .getImage = droid_swrast_get_image, + .putImage2 = droid_swrast_put_image2, +}; + static const __DRImutableRenderBufferLoaderExtension droid_mutable_render_buffer_extension = { .base = {__DRI_MUTABLE_RENDER_BUFFER_LOADER, 1}, @@ -958,6 +1011,15 @@ static const __DRIextension *droid_image_loader_extensions[] = { NULL, }; +static const __DRIextension *droid_swrast_image_loader_extensions[] = { + &droid_image_loader_extension.base, + &image_lookup_extension.base, + &use_invalidate.base, + &droid_mutable_render_buffer_extension.base, + &swrast_loader_extension.base, + NULL, +}; + static EGLBoolean droid_load_driver(_EGLDisplay *disp, bool swrast) { @@ -1137,8 +1199,30 @@ dri2_initialize_android(_EGLDisplay *disp) goto cleanup; } + bool force_pure_swrast = debug_get_bool_option("MESA_ANDROID_NO_KMS_SWRAST", false); + disp->DriverData = (void *)dri2_dpy; - device_opened = droid_open_device(disp, disp->Options.ForceSoftware); + if (!force_pure_swrast) + device_opened = droid_open_device(disp, disp->Options.ForceSoftware); + + if ((!device_opened && disp->Options.ForceSoftware) || + force_pure_swrast) { + dri2_dpy->driver_name = strdup("swrast"); + dri2_dpy->loader_extensions = droid_swrast_image_loader_extensions; + dri2_dpy->fd_render_gpu = -1; + dri2_dpy->pure_swrast = true; + if(!dri2_load_driver(disp)) { + err = "DRI2: Failed to load swrast"; + goto cleanup; + } + + if (!dri2_create_screen(disp)) { + err = "DRI2: Failed to create swrast screen"; + goto cleanup; + } + + device_opened = EGL_TRUE; + } if (!device_opened) { err = "DRI2: failed to open device"; @@ -1147,7 +1231,7 @@ dri2_initialize_android(_EGLDisplay *disp) dri2_dpy->fd_display_gpu = dri2_dpy->fd_render_gpu; - if (!dri2_setup_device(disp, false)) { + if (!dri2_dpy->pure_swrast && !dri2_setup_device(disp, false)) { err = "DRI2: failed to setup EGLDevice"; goto cleanup; } diff --git a/src/gallium/frontends/dri/drisw.c b/src/gallium/frontends/dri/drisw.c index 45759ef178a..73bd0fa4ba6 100644 --- a/src/gallium/frontends/dri/drisw.c +++ b/src/gallium/frontends/dri/drisw.c @@ -43,6 +43,8 @@ #include "dri_helpers.h" #include "dri_query_renderer.h" +#include "util/libsync.h" + #ifdef HAVE_LIBDRM #include #endif @@ -365,6 +367,33 @@ drisw_flush_frontbuffer(struct dri_context *ctx, return true; } +extern bool +dri_image_drawable_get_buffers(struct dri_drawable *drawable, + struct __DRIimageList *images, + const enum st_attachment_type *statts, + unsigned statts_count); + +static void +handle_in_fence(struct dri_context *ctx, __DRIimage *img) +{ + struct pipe_context *pipe = ctx->st->pipe; + struct pipe_fence_handle *fence; + int fd = img->in_fence_fd; + + if (fd == -1) + return; + + validate_fence_fd(fd); + + img->in_fence_fd = -1; + + pipe->create_fence_fd(pipe, &fence, fd, PIPE_FD_TYPE_NATIVE_SYNC); + pipe->fence_server_sync(pipe, fence); + pipe->screen->fence_reference(pipe->screen, &fence, NULL); + + close(fd); +} + /** * Allocate framebuffer attachments. * @@ -384,12 +413,22 @@ drisw_allocate_textures(struct dri_context *stctx, unsigned width, height; bool resized; unsigned i; + const __DRIimageLoaderExtension *image = screen->image.loader; + struct __DRIimageList images; + bool imported_buffers = true; /* Wait for glthread to finish because we can't use pipe_context from * multiple threads. */ _mesa_glthread_finish(stctx->st->ctx); + /* First try to get the buffers from the loader */ + if (image) { + if (!dri_image_drawable_get_buffers(drawable, &images, + statts, count)) + imported_buffers = false; + } + width = drawable->w; height = drawable->h; @@ -413,48 +452,92 @@ drisw_allocate_textures(struct dri_context *stctx, templ.array_size = 1; templ.last_level = 0; - for (i = 0; i < count; i++) { - enum pipe_format format; - unsigned bind; + if (imported_buffers && image) { + if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) { + struct pipe_resource **buf = + &drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; + struct pipe_resource *texture = images.front->texture; - /* the texture already exists or not requested */ - if (drawable->textures[statts[i]]) - continue; + drawable->w = texture->width0; + drawable->h = texture->height0; - dri_drawable_get_format(drawable, statts[i], &format, &bind); + pipe_resource_reference(buf, texture); + handle_in_fence(stctx, images.front); + } - /* if we don't do any present, no need for display targets */ - if (statts[i] != ST_ATTACHMENT_DEPTH_STENCIL && !screen->swrast_no_present) - bind |= PIPE_BIND_DISPLAY_TARGET; + if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) { + struct pipe_resource **buf = + &drawable->textures[ST_ATTACHMENT_BACK_LEFT]; + struct pipe_resource *texture = images.back->texture; - if (format == PIPE_FORMAT_NONE) - continue; + drawable->w = texture->width0; + drawable->h = texture->height0; - templ.format = format; - templ.bind = bind; - templ.nr_samples = 0; - templ.nr_storage_samples = 0; + pipe_resource_reference(buf, texture); + handle_in_fence(stctx, images.back); + } - if (statts[i] == ST_ATTACHMENT_FRONT_LEFT && - screen->base.screen->resource_create_front && - loader->base.version >= 3) { - drawable->textures[statts[i]] = - screen->base.screen->resource_create_front(screen->base.screen, &templ, (const void *)drawable); - } else - drawable->textures[statts[i]] = - screen->base.screen->resource_create(screen->base.screen, &templ); + if (images.image_mask & __DRI_IMAGE_BUFFER_SHARED) { + struct pipe_resource **buf = + &drawable->textures[ST_ATTACHMENT_BACK_LEFT]; + struct pipe_resource *texture = images.back->texture; - if (drawable->stvis.samples > 1) { - templ.bind = templ.bind & - ~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED | PIPE_BIND_DISPLAY_TARGET); - templ.nr_samples = drawable->stvis.samples; - templ.nr_storage_samples = drawable->stvis.samples; - drawable->msaa_textures[statts[i]] = - screen->base.screen->resource_create(screen->base.screen, &templ); + drawable->w = texture->width0; + drawable->h = texture->height0; - dri_pipe_blit(stctx->st->pipe, - drawable->msaa_textures[statts[i]], - drawable->textures[statts[i]]); + pipe_resource_reference(buf, texture); + handle_in_fence(stctx, images.back); + } + + /* Note: if there is both a back and a front buffer, + * then they have the same size. + */ + templ.width0 = drawable->w; + templ.height0 = drawable->h; + } else { + for (i = 0; i < count; i++) { + enum pipe_format format; + unsigned bind; + + /* the texture already exists or not requested */ + if (drawable->textures[statts[i]]) + continue; + + dri_drawable_get_format(drawable, statts[i], &format, &bind); + + /* if we don't do any present, no need for display targets */ + if (statts[i] != ST_ATTACHMENT_DEPTH_STENCIL && !screen->swrast_no_present) + bind |= PIPE_BIND_DISPLAY_TARGET; + + if (format == PIPE_FORMAT_NONE) + continue; + + templ.format = format; + templ.bind = bind; + templ.nr_samples = 0; + templ.nr_storage_samples = 0; + + if (statts[i] == ST_ATTACHMENT_FRONT_LEFT && + screen->base.screen->resource_create_front && + loader->base.version >= 3) { + drawable->textures[statts[i]] = + screen->base.screen->resource_create_front(screen->base.screen, &templ, (const void *)drawable); + } else + drawable->textures[statts[i]] = + screen->base.screen->resource_create(screen->base.screen, &templ); + + if (drawable->stvis.samples > 1) { + templ.bind = templ.bind & + ~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED | PIPE_BIND_DISPLAY_TARGET); + templ.nr_samples = drawable->stvis.samples; + templ.nr_storage_samples = drawable->stvis.samples; + drawable->msaa_textures[statts[i]] = + screen->base.screen->resource_create(screen->base.screen, &templ); + + dri_pipe_blit(stctx->st->pipe, + drawable->msaa_textures[statts[i]], + drawable->textures[statts[i]]); + } } } @@ -614,9 +697,14 @@ drisw_init_screen(struct dri_screen *screen, bool driver_name_is_inferred) } else screen->extensions = drisw_screen_extensions; + #ifdef HAVE_LIBDRM - if (pscreen->resource_create_with_modifiers && (pscreen->get_param(pscreen, PIPE_CAP_DMABUF) & DRM_PRIME_CAP_EXPORT)) + int dmabuf_cap = pscreen->get_param(pscreen, PIPE_CAP_DMABUF); + if (pscreen->resource_create_with_modifiers && (dmabuf_cap & DRM_PRIME_CAP_EXPORT)) screen->extensions[0] = &driVkImageExtension.base; + else if (pscreen->resource_create_with_modifiers && dmabuf_cap) { + driSWImageExtension.createImageFromDmaBufs = driVkImageExtension.createImageFromDmaBufs; + } #endif screen->create_drawable = drisw_create_drawable;