[Mesa-dev] [PATCH] egl: Add swrast support to surfaceless platform
Akihiko Odaki
nekomanma at pixiv.co.jp
Tue Aug 1 05:49:32 UTC 2017
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101397
---
src/egl/drivers/dri2/platform_surfaceless.c | 114 ++++++++++++++++++++++++++--
src/gallium/state_trackers/dri/drisw.c | 45 ++++++++++-
2 files changed, 148 insertions(+), 11 deletions(-)
diff --git a/src/egl/drivers/dri2/platform_surfaceless.c b/src/egl/drivers/dri2/platform_surfaceless.c
index 1091b4febd..5487c89816 100644
--- a/src/egl/drivers/dri2/platform_surfaceless.c
+++ b/src/egl/drivers/dri2/platform_surfaceless.c
@@ -133,9 +133,16 @@ dri2_surfaceless_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type,
if (!config)
goto cleanup_surface;
- dri2_surf->dri_drawable =
- dri2_dpy->image_driver->createNewDrawable(dri2_dpy->dri_screen, config,
- dri2_surf);
+ if (dri2_dpy->image_driver) {
+ dri2_surf->dri_drawable =
+ dri2_dpy->image_driver->createNewDrawable(dri2_dpy->dri_screen, config,
+ dri2_surf);
+ } else {
+ assert(dri2_dpy->swrast);
+ 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, "image->createNewDrawable");
goto cleanup_surface;
@@ -229,7 +236,24 @@ surfaceless_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *dpy)
return (config_count != 0);
}
-static const struct dri2_egl_display_vtbl dri2_surfaceless_display_vtbl = {
+static const struct dri2_egl_display_vtbl dri2_surfaceless_swrast_display_vtbl = {
+ .create_pixmap_surface = dri2_fallback_create_pixmap_surface,
+ .create_pbuffer_surface = dri2_surfaceless_create_pbuffer_surface,
+ .destroy_surface = surfaceless_destroy_surface,
+ .create_image = dri2_create_image_khr,
+ .swap_interval = dri2_fallback_swap_interval,
+ .swap_buffers = surfaceless_swap_buffers,
+ .swap_buffers_region = dri2_fallback_swap_buffers_region,
+ .set_damage_region = dri2_fallback_set_damage_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 const struct dri2_egl_display_vtbl dri2_surfaceless_dri3_display_vtbl = {
.create_pixmap_surface = dri2_fallback_create_pixmap_surface,
.create_pbuffer_surface = dri2_surfaceless_create_pbuffer_surface,
.destroy_surface = surfaceless_destroy_surface,
@@ -252,6 +276,66 @@ surfaceless_flush_front_buffer(__DRIdrawable *driDrawable, void *loaderPrivate)
{
}
+static const __DRIextension *swrast_loader_extensions[] = {
+ NULL,
+};
+
+static EGLBoolean
+dri2_initialize_surfaceless_swrast(_EGLDriver *drv, _EGLDisplay *disp)
+{
+ struct dri2_egl_display *dri2_dpy;
+ const char* err;
+
+ loader_set_logger(_eglLog);
+
+ dri2_dpy = calloc(1, sizeof *dri2_dpy);
+ if (!dri2_dpy)
+ return _eglError(EGL_BAD_ALLOC, "eglInitialize");
+
+ dri2_dpy->fd = -1;
+ disp->DriverData = (void *) dri2_dpy;
+
+ /*
+ * Every hardware driver_name is set using strdup. Doing the same in
+ * here will allow is to simply free the memory at dri2_terminate().
+ */
+ dri2_dpy->driver_name = strdup("swrast");
+ if (!dri2_load_driver_swrast(disp)) {
+ err = "DRI2: failed to load driver";
+ goto cleanup;
+ }
+
+ dri2_dpy->loader_extensions = swrast_loader_extensions;
+
+ if (!dri2_create_screen(disp)) {
+ err = "DRI2: failed to create screen";
+ goto cleanup;
+ }
+
+ if (!dri2_setup_extensions(disp)) {
+ err = "DRI2: failed to find required DRI extensions";
+ goto cleanup;
+ }
+
+ dri2_setup_screen(disp);
+
+ if (!surfaceless_add_configs_for_visuals(drv, disp)) {
+ err = "DRI2: failed to add configs";
+ goto cleanup;
+ }
+
+ /* Fill vtbl last to prevent accidentally calling virtual function during
+ * initialization.
+ */
+ dri2_dpy->vtbl = &dri2_surfaceless_swrast_display_vtbl;
+
+ return EGL_TRUE;
+
+ cleanup:
+ dri2_display_destroy(disp);
+ return _eglError(EGL_NOT_INITIALIZED, err);
+}
+
static const __DRIimageLoaderExtension image_loader_extension = {
.base = { __DRI_IMAGE_LOADER, 1 },
.getBuffers = surfaceless_image_get_buffers,
@@ -267,8 +351,8 @@ static const __DRIextension *image_loader_extensions[] = {
NULL,
};
-EGLBoolean
-dri2_initialize_surfaceless(_EGLDriver *drv, _EGLDisplay *disp)
+static EGLBoolean
+dri2_initialize_surfaceless_dri3(_EGLDriver *drv, _EGLDisplay *disp)
{
struct dri2_egl_display *dri2_dpy;
const char* err;
@@ -336,7 +420,7 @@ dri2_initialize_surfaceless(_EGLDriver *drv, _EGLDisplay *disp)
/* Fill vtbl last to prevent accidentally calling virtual function during
* initialization.
*/
- dri2_dpy->vtbl = &dri2_surfaceless_display_vtbl;
+ dri2_dpy->vtbl = &dri2_surfaceless_dri3_display_vtbl;
return EGL_TRUE;
@@ -344,3 +428,19 @@ cleanup:
dri2_display_destroy(disp);
return _eglError(EGL_NOT_INITIALIZED, err);
}
+
+EGLBoolean
+dri2_initialize_surfaceless(_EGLDriver *drv, _EGLDisplay *disp)
+{
+ EGLBoolean initialized = EGL_FALSE;
+
+ if (!getenv("LIBGL_ALWAYS_SOFTWARE")) {
+ initialized = dri2_initialize_surfaceless_dri3(drv, disp);
+ }
+
+ if (!initialized) {
+ initialized = dri2_initialize_surfaceless_swrast(drv, disp);
+ }
+
+ return initialized;
+}
diff --git a/src/gallium/state_trackers/dri/drisw.c b/src/gallium/state_trackers/dri/drisw.c
index ac4095618c..0d1825defa 100644
--- a/src/gallium/state_trackers/dri/drisw.c
+++ b/src/gallium/state_trackers/dri/drisw.c
@@ -52,6 +52,10 @@
DEBUG_GET_ONCE_BOOL_OPTION(swrast_no_present, "SWRAST_NO_PRESENT", FALSE);
static boolean swrast_no_present = FALSE;
+/* Check dPriv->driScreenPriv->swrast_loader before calling this function
+ * since this function refers to the pointer and it would be NULL for offscreen
+ * rendering.
+ */
static inline void
get_drawable_info(__DRIdrawable *dPriv, int *x, int *y, int *w, int *h)
{
@@ -63,6 +67,9 @@ get_drawable_info(__DRIdrawable *dPriv, int *x, int *y, int *w, int *h)
dPriv->loaderPrivate);
}
+/* Check dPriv->driScreenPriv->swrast_loader before calling this function
+ * (c.f. get_drawable_info)
+ */
static inline void
put_image(__DRIdrawable *dPriv, void *data, unsigned width, unsigned height)
{
@@ -74,6 +81,9 @@ put_image(__DRIdrawable *dPriv, void *data, unsigned width, unsigned height)
data, dPriv->loaderPrivate);
}
+/* Check dPriv->driScreenPriv->swrast_loader before calling this function
+ * (c.f. get_drawable_info)
+ */
static inline void
put_image2(__DRIdrawable *dPriv, void *data, int x, int y,
unsigned width, unsigned height, unsigned stride)
@@ -86,6 +96,9 @@ put_image2(__DRIdrawable *dPriv, void *data, int x, int y,
data, dPriv->loaderPrivate);
}
+/* Check dPriv->driScreenPriv->swrast_loader before calling this function
+ * (c.f. get_drawable_info)
+ */
static inline void
get_image(__DRIdrawable *dPriv, int x, int y, int width, int height, void *data)
{
@@ -97,6 +110,9 @@ get_image(__DRIdrawable *dPriv, int x, int y, int width, int height, void *data)
data, dPriv->loaderPrivate);
}
+/* Check dPriv->driScreenPriv->swrast_loader before calling this function
+ * (c.f. get_drawable_info)
+ */
static inline void
get_image2(__DRIdrawable *dPriv, int x, int y, int width, int height, int stride, void *data)
{
@@ -112,6 +128,9 @@ get_image2(__DRIdrawable *dPriv, int x, int y, int width, int height, int stride
data, dPriv->loaderPrivate);
}
+/* Check drawable->dPriv->driScreenPriv->swrast_loader before calling this
+ * function (c.f. get_drawable_info)
+ */
static void
drisw_update_drawable_info(struct dri_drawable *drawable)
{
@@ -121,6 +140,9 @@ drisw_update_drawable_info(struct dri_drawable *drawable)
get_drawable_info(dPriv, &x, &y, &dPriv->w, &dPriv->h);
}
+/* Check drawable->dPriv->driScreenPriv->swrast_loader before calling this
+ * function (c.f. get_drawable_info and get_image2)
+ */
static void
drisw_get_image(struct dri_drawable *drawable,
int x, int y, unsigned width, unsigned height, unsigned stride,
@@ -133,6 +155,9 @@ drisw_get_image(struct dri_drawable *drawable,
get_image2(dPriv, x, y, draw_w, draw_h, stride, data);
}
+/* Check drawable->dPriv->driScreenPriv->swrast_loader before calling this function
+ * (c.f. put_image)
+ */
static void
drisw_put_image(struct dri_drawable *drawable,
void *data, unsigned width, unsigned height)
@@ -142,6 +167,9 @@ drisw_put_image(struct dri_drawable *drawable,
put_image(dPriv, data, width, height);
}
+/* Check drawable->dPriv->driScreenPriv->swrast_loader before calling this function
+ * (c.f. put_image2)
+ */
static void
drisw_put_image2(struct dri_drawable *drawable,
void *data, int x, int y, unsigned width, unsigned height,
@@ -313,7 +341,7 @@ drisw_allocate_textures(struct dri_context *stctx,
if (statts[i] == ST_ATTACHMENT_FRONT_LEFT &&
screen->base.screen->resource_create_front &&
- loader->base.version >= 3) {
+ loader && loader->base.version >= 3) {
drawable->textures[statts[i]] =
screen->base.screen->resource_create_front(screen->base.screen, &templ, (const void *)drawable);
} else
@@ -325,6 +353,9 @@ drisw_allocate_textures(struct dri_context *stctx,
drawable->old_h = height;
}
+/* Check drawable->dPriv->driScreenPriv->swrast_loader before calling this
+ * function (c.f. get_drawable_info and get_image)
+ */
static void
drisw_update_tex_buffer(struct dri_drawable *drawable,
struct dri_context *ctx,
@@ -375,6 +406,9 @@ static const __DRIextension *drisw_screen_extensions[] = {
NULL
};
+/* Check drawable->dPriv->driScreenPriv->swrast_loader before referring to
+ * functions referred by this structure.
+ */
static struct drisw_loader_funcs drisw_lf = {
.get_image = drisw_get_image,
.put_image = drisw_put_image,
@@ -402,7 +436,7 @@ drisw_init_screen(__DRIscreen * sPriv)
unsigned flags = dri_init_options_get_screen_flags(screen, "swrast");
- if (pipe_loader_sw_probe_dri(&screen->dev, &drisw_lf))
+ if (pipe_loader_sw_probe_dri(&screen->dev, sPriv->swrast_loader ? &drisw_lf : NULL))
pscreen = pipe_loader_create_screen(screen->dev, flags);
if (!pscreen)
@@ -434,9 +468,12 @@ drisw_create_buffer(__DRIscreen * sPriv,
drawable = dPriv->driverPrivate;
drawable->allocate_textures = drisw_allocate_textures;
- drawable->update_drawable_info = drisw_update_drawable_info;
drawable->flush_frontbuffer = drisw_flush_frontbuffer;
- drawable->update_tex_buffer = drisw_update_tex_buffer;
+
+ if (sPriv->swrast_loader) {
+ drawable->update_drawable_info = drisw_update_drawable_info;
+ drawable->update_tex_buffer = drisw_update_tex_buffer;
+ }
return TRUE;
}
--
2.13.3
More information about the mesa-dev
mailing list