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/desktop-shell/shell.c b/desktop-shell/shell.c
index c18b6b4..07c0aba 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -2966,6 +2966,22 @@
weston_surface_set_label_func(surface, background_get_label);
surface->output = weston_output_from_resource(output_resource);
view->output = surface->output;
+
+ char *p;
+ p = getenv("DESKTOP_SHELL_WINDOW");
+ if (p) {
+ int32_t width, height;
+ int n;
+
+ n = sscanf(p, "%dx%d", &width, &height);
+ if (n == 2) {
+ if (surface->output->width > width)
+ surface->output->width = width;
+ if (surface->output->height > height)
+ surface->output->height = height;
+ }
+ }
+
weston_desktop_shell_send_configure(resource, 0,
surface_resource,
surface->output->width,
@@ -3052,6 +3068,22 @@
weston_surface_set_label_func(surface, panel_get_label);
surface->output = weston_output_from_resource(output_resource);
view->output = surface->output;
+
+ char *p;
+ p = getenv("DESKTOP_SHELL_WINDOW");
+ if (p) {
+ int32_t width, height;
+ int n;
+
+ n = sscanf(p, "%dx%d", &width, &height);
+ if (n == 2) {
+ if (surface->output->width > width)
+ surface->output->width = width;
+ if (surface->output->height > height)
+ surface->output->height = height;
+ }
+ }
+
weston_desktop_shell_send_configure(resource, 0,
surface_resource,
surface->output->width,
diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index 50be373..8c7da81 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -51,7 +51,12 @@
#include "compositor-drm.h"
#include "shared/helpers.h"
#include "shared/timespec-util.h"
+#if defined(ENABLE_OPENGL)
#include "gl-renderer.h"
+#endif
+#if defined(ENABLE_IMXG2D)
+#include "g2d-renderer.h"
+#endif
#include "weston-egl-ext.h"
#include "pixman-renderer.h"
#include "pixel-formats.h"
@@ -277,6 +282,9 @@
bool atomic_modeset;
int use_pixman;
+#if defined(ENABLE_IMXG2D)
+ int use_g2d;
+#endif
struct udev_input input;
@@ -470,6 +478,9 @@
struct drm_fb *dumb[2];
pixman_image_t *image[2];
+#if defined(ENABLE_IMXG2D)
+ struct g2d_surfaceEx g2d_image[2];
+#endif
int current_image;
pixman_region32_t previous_damage;
@@ -479,7 +490,12 @@
struct wl_event_source *pageflip_timer;
};
+#if defined(ENABLE_OPENGL)
static struct gl_renderer_interface *gl_renderer;
+#endif
+#if defined(ENABLE_IMXG2D)
+static struct g2d_renderer_interface *g2d_renderer;
+#endif
static const char default_seat[] = "seat0";
@@ -890,7 +906,8 @@
fb->offsets, mods, &fb->fb_id,
DRM_MODE_FB_MODIFIERS);
#endif
- return ret;
+ if (ret == 0)
+ return ret;
}
ret = drmModeAddFB2(fb->fd, fb->width, fb->height, fb->format->format,
@@ -1934,6 +1951,36 @@
return drm_fb_ref(output->dumb[output->current_image]);
}
+#if 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)
{
@@ -1943,6 +1990,7 @@
struct drm_plane *scanout_plane = output->scanout_plane;
struct drm_backend *b = to_drm_backend(c);
struct drm_fb *fb;
+ char *p;
/* If we already have a client buffer promoted to scanout, then we don't
* want to render. */
@@ -1953,7 +2001,11 @@
scanout_state->fb->type != BUFFER_PIXMAN_DUMB)
return;
- if (!pixman_region32_not_empty(damage) &&
+ if (
+#if defined(ENABLE_IMXG2D)
+ !b->use_g2d &&
+#endif
+ !pixman_region32_not_empty(damage) &&
scanout_plane->state_cur->fb &&
(scanout_plane->state_cur->fb->type == BUFFER_GBM_SURFACE ||
scanout_plane->state_cur->fb->type == BUFFER_PIXMAN_DUMB) &&
@@ -1964,9 +2016,15 @@
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_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
if (!fb) {
drm_plane_state_put_back(scanout_state);
@@ -1987,7 +2045,18 @@
scanout_state->dest_w = scanout_state->src_w >> 16;
scanout_state->dest_h = scanout_state->src_h >> 16;
-
+ p = getenv("DESKTOP_SHELL_WINDOW");
+ if (p) {
+ uint32_t width, height;
+ int n;
+ n = sscanf(p, "%dx%d", &width, &height);
+ if (n == 2) {
+ if (scanout_state->src_w > (width << 16))
+ scanout_state->src_w = width << 16;
+ if (scanout_state->src_h > (height << 16))
+ scanout_state->src_h = height << 16;
+ }
+ }
pixman_region32_subtract(&c->primary_plane.damage,
&c->primary_plane.damage, damage);
}
@@ -2105,14 +2174,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 ||
@@ -3456,14 +3519,22 @@
return tmp_mode;
}
+#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
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_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
static int
drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mode)
@@ -3502,6 +3573,16 @@
"new mode\n");
return -1;
}
+#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) {
@@ -3509,6 +3590,7 @@
"new mode");
return -1;
}
+#endif
}
return 0;
@@ -3604,6 +3686,7 @@
return 0;
}
+#if defined(ENABLE_OPENGL)
static struct gbm_device *
create_gbm_device(int fd)
{
@@ -3689,6 +3772,7 @@
return 0;
}
+#endif
static int
init_pixman(struct drm_backend *b)
@@ -3696,6 +3780,43 @@
return pixman_renderer_init(b->compositor);
}
+#if 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_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
+
/**
* Populates the formats array, and the modifiers of each format for a drm_plane.
*/
@@ -4365,6 +4486,7 @@
return -1;
}
+#if 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)
@@ -4429,7 +4551,9 @@
return 0;
}
+#endif
+#if defined(ENABLE_OPENGL)
static void
drm_output_fini_egl(struct drm_output *output)
{
@@ -4450,6 +4574,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)
@@ -4536,6 +4661,80 @@
}
}
+#if 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;
+ output->dumb[i] = drm_fb_create_dumb(b, w, h, format);
+ if (!output->dumb[i])
+ 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);
+ 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_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[])
{
@@ -4765,6 +4964,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)
@@ -4961,9 +5162,18 @@
weston_log("Failed to init output pixman state\n");
goto err;
}
+#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
}
if (output->backlight) {
@@ -5020,8 +5230,14 @@
if (b->use_pixman)
drm_output_fini_pixman(output);
+#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
/* Since our planes are no longer in use anywhere, remove their base
* weston_plane's link from the plane stacking list, unless we're
@@ -5868,6 +6084,7 @@
}
#endif
+#if defined(ENABLE_OPENGL)
static void
switch_to_gl_renderer(struct drm_backend *b)
{
@@ -5911,7 +6128,9 @@
"support failed.\n");
}
}
+#endif
+#if defined(ENABLE_OPENGL)
static void
renderer_switch_binding(struct weston_keyboard *keyboard,
const struct timespec *time, uint32_t key, void *data)
@@ -5921,6 +6140,7 @@
switch_to_gl_renderer(b);
}
+#endif
static const struct weston_drm_output_api api = {
drm_output_set_mode,
@@ -5951,6 +6171,9 @@
b->compositor = compositor;
b->use_pixman = config->use_pixman;
+#if defined(ENABLE_IMXG2D)
+ b->use_g2d = config->use_g2d;
+#endif
b->pageflip_timeout = config->pageflip_timeout;
compositor->backend = &b->base;
@@ -5999,11 +6222,20 @@
weston_log("failed to initialize pixman renderer\n");
goto err_udev_dev;
}
+#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
}
b->base.destroy = drm_destroy;
@@ -6021,7 +6253,6 @@
compositor, b->udev, seat_id,
config->configure_device) < 0) {
weston_log("failed to create input devices\n");
- goto err_sprite;
}
if (create_outputs(b, drm_device) < 0) {
@@ -6066,8 +6297,10 @@
planes_binding, b);
weston_compositor_add_debug_binding(compositor, KEY_Q,
recorder_binding, b);
+#if 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)
@@ -6092,7 +6325,6 @@
wl_event_source_remove(b->drm_source);
err_udev_input:
udev_input_destroy(&b->input);
-err_sprite:
if (b->gbm)
gbm_device_destroy(b->gbm);
destroy_sprites(b);
@@ -6111,6 +6343,14 @@
static void
config_init_to_defaults(struct weston_drm_backend_config *config)
{
+#if !defined(ENABLE_OPENGL) && !defined(ENABLE_IMXG2D)
+ config->use_pixman = 1;
+#else
+ config->use_pixman = 0;
+#endif
+#if !defined(ENABLE_OPENGL) && defined(ENABLE_IMXG2D)
+ config->use_g2d = 1;
+#endif
}
WL_EXPORT int