compositor: Add G2d render in DRM compositor
Upstream-Status: Inappropriate [i.MX-specific]
Signed-off-by: Yong Gan <yong.gan@nxp.com>
diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index 3891176..bf0a227 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -53,7 +53,16 @@
#include "compositor-drm.h"
#include "shared/helpers.h"
#include "shared/timespec-util.h"
+
+#if defined(ENABLE_IMXGPU)
+#if defined(ENABLE_OPENGL)
#include "gl-renderer.h"
+#endif
+#if defined(ENABLE_IMXG2D)
+#include "g2d-renderer.h"
+#endif
+#endif
+
#include "weston-egl-ext.h"
#include "pixman-renderer.h"
#include "pixel-formats.h"
@@ -290,6 +299,9 @@
bool atomic_modeset;
int use_pixman;
+#if defined(ENABLE_IMXGPU) && defined(ENABLE_IMXG2D)
+ int use_g2d;
+#endif
bool use_pixman_shadow;
struct udev_input input;
@@ -496,6 +508,9 @@
struct drm_fb *dumb[2];
pixman_image_t *image[2];
+#if defined(ENABLE_IMXGPU) && defined(ENABLE_IMXG2D)
+ struct g2d_surfaceEx g2d_image[2];
+#endif
int current_image;
pixman_region32_t previous_damage;
@@ -513,7 +528,14 @@
[WESTON_MODE_PIC_AR_256_135] = " 256:135",
};
+#if defined(ENABLE_IMXGPU)
+#if defined(ENABLE_OPENGL)
static struct gl_renderer_interface *gl_renderer;
+#endif
+#if defined(ENABLE_IMXG2D)
+static struct g2d_renderer_interface *g2d_renderer;
+#endif
+#endif
static const char default_seat[] = "seat0";
@@ -2052,6 +2074,36 @@
return drm_fb_ref(output->dumb[output->current_image]);
}
+#if defined(ENABLE_IMXGPU) && defined(ENABLE_IMXG2D)
+static struct drm_fb *
+drm_output_render_g2d(struct drm_output_state *state, pixman_region32_t *damage)
+{
+ struct drm_output *output = state->output;
+ struct weston_compositor *ec = output->base.compositor;
+ pixman_region32_t total_damage, previous_damage;
+
+ pixman_region32_init(&total_damage);
+ pixman_region32_init(&previous_damage);
+
+ pixman_region32_copy(&previous_damage, damage);
+
+ pixman_region32_union(&total_damage, damage, &output->previous_damage);
+ pixman_region32_copy(&output->previous_damage, &previous_damage);
+
+ output->current_image ^= 1;
+
+ g2d_renderer->output_set_buffer(&output->base,
+ &output->g2d_image[output->current_image]);
+
+ ec->renderer->repaint_output(&output->base, &total_damage);
+
+ pixman_region32_fini(&total_damage);
+ pixman_region32_fini(&previous_damage);
+
+ return drm_fb_ref(output->dumb[output->current_image]);
+}
+#endif
+
static void
drm_output_render(struct drm_output_state *state, pixman_region32_t *damage)
{
@@ -2080,9 +2132,17 @@
fb = drm_fb_ref(scanout_plane->state_cur->fb);
} else if (b->use_pixman) {
fb = drm_output_render_pixman(state, damage);
- } else {
- fb = drm_output_render_gl(state, damage);
}
+#if defined(ENABLE_IMXGPU)
+#if defined(ENABLE_IMXG2D)
+ else if (b->use_g2d)
+ fb = drm_output_render_g2d(state, damage);
+#endif
+#if defined(ENABLE_OPENGL)
+ else
+ fb = drm_output_render_gl(state, damage);
+#endif
+#endif
if (!fb) {
drm_plane_state_put_back(scanout_state);
@@ -2228,14 +2288,8 @@
* legacy PageFlip API doesn't allow us to do clipping either. */
assert(scanout_state->src_x == 0);
assert(scanout_state->src_y == 0);
- assert(scanout_state->src_w ==
- (unsigned) (output->base.current_mode->width << 16));
- assert(scanout_state->src_h ==
- (unsigned) (output->base.current_mode->height << 16));
assert(scanout_state->dest_x == 0);
assert(scanout_state->dest_y == 0);
- assert(scanout_state->dest_w == scanout_state->src_w >> 16);
- assert(scanout_state->dest_h == scanout_state->src_h >> 16);
mode = to_drm_mode(output->base.current_mode);
if (backend->state_invalid ||
@@ -3689,13 +3743,23 @@
}
static int
-drm_output_init_egl(struct drm_output *output, struct drm_backend *b);
-static void
-drm_output_fini_egl(struct drm_output *output);
-static int
drm_output_init_pixman(struct drm_output *output, struct drm_backend *b);
static void
drm_output_fini_pixman(struct drm_output *output);
+#if defined(ENABLE_IMXGPU)
+#if defined(ENABLE_OPENGL)
+static int
+drm_output_init_egl(struct drm_output *output, struct drm_backend *b);
+static void
+drm_output_fini_egl(struct drm_output *output);
+#endif
+#if defined(ENABLE_IMXG2D)
+static int
+drm_output_init_g2d(struct drm_output *output, struct drm_backend *b);
+static void
+drm_output_fini_g2d(struct drm_output *output);
+#endif
+#endif
static int
drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mode)
@@ -3734,6 +3798,17 @@
"new mode\n");
return -1;
}
+#if defined(ENABLE_IMXGPU)
+#if defined(ENABLE_IMXG2D)
+ } else if (b->use_g2d) {
+ drm_output_fini_g2d(output);
+ if (drm_output_init_g2d(output, b) < 0) {
+ weston_log("failed to init output g2d state with "
+ "new mode\n");
+ return -1;
+ }
+#endif
+#if defined(ENABLE_OPENGL)
} else {
drm_output_fini_egl(output);
if (drm_output_init_egl(output, b) < 0) {
@@ -3741,6 +3816,8 @@
"new mode");
return -1;
}
+#endif
+#endif
}
return 0;
@@ -3841,6 +3918,7 @@
return 0;
}
+#if defined(ENABLE_IMXGPU) && defined(ENABLE_OPENGL)
static struct gbm_device *
create_gbm_device(int fd)
{
@@ -3926,6 +4004,7 @@
return 0;
}
+#endif
static int
init_pixman(struct drm_backend *b)
@@ -3933,6 +4012,43 @@
return pixman_renderer_init(b->compositor);
}
+#if defined(ENABLE_IMXGPU) && defined(ENABLE_IMXG2D)
+static int
+drm_backend_create_g2d_renderer(struct drm_backend *b)
+{
+ if (g2d_renderer->drm_display_create(b->compositor,
+ (void *)b->gbm) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+#if defined(ENABLE_IMXGPU) && defined(ENABLE_IMXG2D)
+static int
+init_g2d(struct drm_backend *b)
+{
+ g2d_renderer = weston_load_module("g2d-renderer.so",
+ "g2d_renderer_interface");
+ if (!g2d_renderer) {
+ weston_log("Could not load g2d renderer\n");
+ return -1;
+ }
+
+ b->gbm = gbm_create_device(b->drm.fd);
+ if (!b->gbm)
+ return -1;
+
+ if (drm_backend_create_g2d_renderer(b) < 0) {
+ gbm_device_destroy(b->gbm);
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
#ifdef HAVE_DRM_FORMATS_BLOB
static inline uint32_t *
formats_ptr(struct drm_format_modifier_blob *blob)
@@ -4627,6 +4743,7 @@
return -1;
}
+#if defined(ENABLE_IMXGPU) && defined(ENABLE_OPENGL)
/* Init output state that depends on gl or gbm */
static int
drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
@@ -4691,7 +4808,9 @@
return 0;
}
+#endif
+#if defined(ENABLE_IMXGPU) && defined(ENABLE_OPENGL)
static void
drm_output_fini_egl(struct drm_output *output)
{
@@ -4712,6 +4831,7 @@
gbm_surface_destroy(output->gbm_surface);
drm_output_fini_cursor_egl(output);
}
+#endif
static int
drm_output_init_pixman(struct drm_output *output, struct drm_backend *b)
@@ -4805,6 +4925,86 @@
}
}
+#if defined(ENABLE_IMXGPU) && defined(ENABLE_IMXG2D)
+static int
+drm_output_init_g2d(struct drm_output *output, struct drm_backend *b)
+{
+ int w = output->base.current_mode->width;
+ int h = output->base.current_mode->height;
+ uint32_t format = output->gbm_format;
+ enum g2d_format g2dFormat;
+ uint32_t i = 0;
+
+ switch (format) {
+ case GBM_FORMAT_XRGB8888:
+ g2dFormat = G2D_BGRX8888;
+ break;
+ case GBM_FORMAT_RGB565:
+ g2dFormat = G2D_RGB565;
+ break;
+ default:
+ weston_log("Unsupported pixman format 0x%x\n", format);
+ return -1;
+ }
+
+ for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
+ struct g2d_surfaceEx* g2dSurface = &(output->g2d_image[i]);
+ int ret, dmafd = 0;
+ output->dumb[i] = drm_fb_create_dumb(b, w, h, format);
+ if (!output->dumb[i])
+ goto err;
+
+ ret = drmPrimeHandleToFD(b->drm.fd, output->dumb[i]->handles[0], DRM_CLOEXEC,
+ &dmafd);
+ if(ret < 0)
+ goto err;
+
+ ret = g2d_renderer->create_g2d_image(g2dSurface, g2dFormat,
+ output->dumb[i]->map,
+ w, h,
+ output->dumb[i]->strides[0],
+ output->dumb[i]->size,
+ dmafd);
+ if (ret < 0)
+ goto err;
+ }
+
+ if (g2d_renderer->drm_output_create(&output->base) < 0)
+ goto err;
+
+ drm_output_init_cursor_egl(output, b);
+
+ return 0;
+
+err:
+ weston_log("drm_output_init_g2d failed.\n");
+ for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
+ if (output->dumb[i])
+ drm_fb_unref(output->dumb[i]);
+
+ output->dumb[i] = NULL;
+ }
+
+ return -1;
+}
+#endif
+
+#if defined(ENABLE_IMXGPU) && defined(ENABLE_IMXG2D)
+static void
+drm_output_fini_g2d(struct drm_output *output)
+{
+ unsigned int i;
+
+ pixman_region32_fini(&output->previous_damage);
+
+ for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
+ drm_fb_unref(output->dumb[i]);
+ output->dumb[i] = NULL;
+ }
+ g2d_renderer->output_destroy(&output->base);
+}
+#endif
+
static void
edid_parse_string(const uint8_t *data, char text[])
{
@@ -5076,6 +5276,8 @@
*gbm_format = default_value;
else if (strcmp(s, "xrgb8888") == 0)
*gbm_format = GBM_FORMAT_XRGB8888;
+ else if (strcmp(s, "argb8888") == 0)
+ *gbm_format = GBM_FORMAT_ARGB8888;
else if (strcmp(s, "rgb565") == 0)
*gbm_format = GBM_FORMAT_RGB565;
else if (strcmp(s, "xrgb2101010") == 0)
@@ -5749,9 +5951,20 @@
weston_log("Failed to init output pixman state\n");
goto err;
}
+#if defined(ENABLE_IMXGPU)
+#if defined(ENABLE_IMXG2D)
+ } else if (b->use_g2d) {
+ if (drm_output_init_g2d(output, b) < 0) {
+ weston_log("Failed to init output g2d state\n");
+ goto err;
+ }
+#endif
+#if defined(ENABLE_OPENGL)
} else if (drm_output_init_egl(output, b) < 0) {
weston_log("Failed to init output gl state\n");
goto err;
+#endif
+#endif
}
drm_output_init_backlight(output);
@@ -5794,8 +6007,16 @@
if (b->use_pixman)
drm_output_fini_pixman(output);
+#if defined(ENABLE_IMXGPU)
+#if defined(ENABLE_IMXG2D)
+ else if (b->use_g2d)
+ drm_output_fini_g2d(output);
+#endif
+#if defined(ENABLE_OPENGL)
else
drm_output_fini_egl(output);
+#endif
+#endif
/* Since our planes are no longer in use anywhere, remove their base
* weston_plane's link from the plane stacking list, unless we're
@@ -6628,6 +6849,7 @@
}
#endif
+#if defined(ENABLE_IMXGPU) && defined(ENABLE_OPENGL)
static void
switch_to_gl_renderer(struct drm_backend *b)
{
@@ -6671,7 +6893,9 @@
"support failed.\n");
}
}
+#endif
+#if defined(ENABLE_IMXGPU) && defined(ENABLE_OPENGL)
static void
renderer_switch_binding(struct weston_keyboard *keyboard,
const struct timespec *time, uint32_t key, void *data)
@@ -6681,6 +6905,7 @@
switch_to_gl_renderer(b);
}
+#endif
static const struct weston_drm_output_api api = {
drm_output_set_mode,
@@ -6718,6 +6943,9 @@
b->compositor = compositor;
b->use_pixman = config->use_pixman;
+#if defined(ENABLE_IMXGPU) && defined(ENABLE_IMXG2D)
+ b->use_g2d = config->use_g2d;
+#endif
b->pageflip_timeout = config->pageflip_timeout;
b->use_pixman_shadow = config->use_pixman_shadow;
@@ -6764,11 +6992,22 @@
weston_log("failed to initialize pixman renderer\n");
goto err_udev_dev;
}
+#if defined(ENABLE_IMXGPU)
+#if defined(ENABLE_IMXG2D)
+ } else if(b->use_g2d){
+ if (init_g2d(b) < 0) {
+ weston_log("failed to initialize g2d render\n");
+ goto err_udev_dev;
+ }
+#endif
+#if defined(ENABLE_OPENGL)
} else {
if (init_egl(b) < 0) {
weston_log("failed to initialize egl\n");
goto err_udev_dev;
}
+#endif
+#endif
}
b->base.destroy = drm_destroy;
@@ -6831,8 +7070,10 @@
planes_binding, b);
weston_compositor_add_debug_binding(compositor, KEY_Q,
recorder_binding, b);
+#if defined(ENABLE_IMXGPU) && defined(ENABLE_OPENGL)
weston_compositor_add_debug_binding(compositor, KEY_W,
renderer_switch_binding, b);
+#endif
if (compositor->renderer->import_dmabuf) {
if (linux_dmabuf_setup(compositor) < 0)
@@ -6876,7 +7117,20 @@
static void
config_init_to_defaults(struct weston_drm_backend_config *config)
{
+#if !defined(ENABLE_IMXGPU) || !defined(ENABLE_OPENGL) && !defined(ENABLE_IMXG2D)
+ config->use_pixman = 1;
config->use_pixman_shadow = true;
+#else
+ config->use_pixman = 0;
+ config->use_pixman_shadow = false;
+#endif
+#if defined(ENABLE_IMXGPU) && defined(ENABLE_IMXG2D)
+#if !defined(ENABLE_OPENGL)
+ config->use_g2d = 1;
+#else
+ config->use_g2d = 0;
+#endif
+#endif
}
WL_EXPORT int