compositor: Add G2d render in FBDev compositor

Upstream-Status: Inappropriate [i.MX-specific]

Signed-off-by: Yong Gan <yong.gan@nxp.com>
diff --git a/Makefile.am b/Makefile.am
index 83bb253..e4da7b9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -305,16 +305,18 @@
 	ivi-shell/ivi-layout-export.h
 endif
 
-if ENABLE_EGL
+if ENABLE_OPENGL
 libweston_module_LTLIBRARIES += gl-renderer.la
 gl_renderer_la_LDFLAGS = -module -avoid-version
 gl_renderer_la_LIBADD =				\
 	libweston-@LIBWESTON_MAJOR@.la		\
 	$(EGL_LIBS)				\
+	$(OPENGL_LIBS)				\
 	$(COMPOSITOR_LIBS)
 gl_renderer_la_CFLAGS =				\
 	$(COMPOSITOR_CFLAGS)			\
 	$(EGL_CFLAGS)				\
+	$(GL_RENDERER_CFLAGS)			\
 	$(LIBDRM_CFLAGS)			\
 	$(AM_CFLAGS)
 gl_renderer_la_SOURCES =			\
@@ -326,6 +328,29 @@
 	shared/helpers.h
 endif
 
+if ENABLE_IMXG2D
+libweston_module_LTLIBRARIES += g2d-renderer.la
+g2d_renderer_la_LDFLAGS = -module -avoid-version
+g2d_renderer_la_LIBADD = 			\
+	libweston-@LIBWESTON_MAJOR@.la		\
+	$(EGL_LIBS)				\
+	$(COMPOSITOR_LIBS)			\
+	-lg2d
+g2d_renderer_la_CFLAGS =			\
+	$(COMPOSITOR_CFLAGS)			\
+	$(LIBDRM_CFLAGS)			\
+	$(EGL_CFLAGS)				\
+	$(GCC_CFLAGS) -DHAVE_G2D
+g2d_renderer_la_SOURCES =			\
+	libweston/g2d-renderer.h			\
+	libweston/g2d-renderer.c			\
+	libweston/vertex-clipping.c			\
+	libweston/vertex-clipping.h
+if ENABLE_EGL
+g2d_renderer_la_CFLAGS += -DENABLE_EGL
+endif
+endif
+
 if ENABLE_X11_COMPOSITOR
 libweston_module_LTLIBRARIES += x11-backend.la
 x11_backend_la_LDFLAGS = -module -avoid-version
diff --git a/compositor/main.c b/compositor/main.c
index b5b4fc5..7d1da2c 100644
--- a/compositor/main.c
+++ b/compositor/main.c
@@ -516,7 +516,16 @@
 		"  --seat=SEAT\t\tThe seat that weston should run on, instead of the seat defined in XDG_SEAT\n"
 		"  --tty=TTY\t\tThe tty to use\n"
 		"  --drm-device=CARD\tThe DRM device to use, e.g. \"card0\".\n"
-		"  --use-pixman\t\tUse the pixman (CPU) renderer\n"
+#if defined(ENABLE_IMXGPU)
+#if defined(ENABLE_OPENGL)
+		"  --use-pixman\t\tUse the pixman (CPU) renderer (default: GL rendering)\n"
+#elif defined(ENABLE_IMXG2D)
+		"  --use-pixman\t\tUse the pixman (CPU) renderer (default: G2D rendering)\n"
+#endif
+#if defined(ENABLE_OPENGL) && defined(ENABLE_IMXG2D)
+		"  --use-g2d=1\t\tUse the G2D renderer (default: GL rendering)\n"
+#endif
+#endif
 		"  --current-mode\tPrefer current KMS mode over EDID preferred mode\n\n");
 #endif
 
@@ -525,6 +534,21 @@
 		"Options for fbdev-backend.so:\n\n"
 		"  --tty=TTY\t\tThe tty to use\n"
 		"  --device=DEVICE\tThe framebuffer device to use\n"
+#if defined(ENABLE_IMXGPU)
+#if defined(ENABLE_OPENGL)
+		"  --use-pixman\t\tUse the pixman (CPU) renderer (default: GL rendering)\n"
+#elif defined(ENABLE_IMXG2D)
+		"  --use-pixman\t\tUse the pixman (CPU) renderer (default: G2D rendering)\n"
+#endif
+#if defined(ENABLE_OPENGL) && defined(ENABLE_IMXG2D)
+		"  --use-g2d=1\t\tUse the G2D renderer (default: GL rendering)\n"
+#endif
+#if defined(ENABLE_IMXG2D)
+		"  --device=DEVICE[,DEVICE]...\n"
+		"  \t\t\tG2D-only: The framebuffer device(s) to use\n"
+		"  --clone-mode\t\tG2D-only: Duplicate the display on the specified devices\n"
+#endif
+#endif
 		"  --seat=SEAT\t\tThe seat that weston should run on, instead of the seat defined in XDG_SEAT\n"
 		"\n");
 #endif
@@ -1844,11 +1868,22 @@
 		{ WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
 		{ WESTON_OPTION_STRING, "drm-device", 0, &config.specific_device },
 		{ WESTON_OPTION_BOOLEAN, "current-mode", 0, &wet->drm_use_current_mode },
+#if defined(ENABLE_IMXGPU)
+#if defined(ENABLE_OPENGL) || defined(ENABLE_IMXG2D)
 		{ WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
+#endif
+#if defined(ENABLE_OPENGL) && defined(ENABLE_IMXG2D)
+		{ WESTON_OPTION_INTEGER, "use-g2d", 0, &config.use_g2d },
+#endif
+#endif
 	};
 
 	parse_options(options, ARRAY_LENGTH(options), argc, argv);
-
+#if !defined(ENABLE_IMXGPU) || !defined(ENABLE_OPENGL) && !defined(ENABLE_IMXG2D)
+	config.use_pixman = 1;
+#elif !defined(ENABLE_OPENGL)
+	config.use_g2d = 1;
+#endif
 	section = weston_config_get_section(wc, "core", NULL, NULL);
 	weston_config_section_get_string(section,
 					 "gbm-format", &config.gbm_format,
@@ -2061,9 +2096,25 @@
 		{ WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
 		{ WESTON_OPTION_STRING, "device", 0, &config.device },
 		{ WESTON_OPTION_STRING, "seat", 0, &config.seat_id },
+#if defined(ENABLE_IMXGPU)
+#if defined(ENABLE_OPENGL) || defined(ENABLE_IMXG2D)
+		{ WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
+#endif
+#if defined(ENABLE_OPENGL) && defined(ENABLE_IMXG2D)
+		{ WESTON_OPTION_INTEGER, "use-g2d", 0, &config.use_g2d },
+#endif
+#if defined(ENABLE_IMXG2D)
+		{ WESTON_OPTION_BOOLEAN, "clone-mode", 0, &config.clone_mode },
+#endif
+#endif
 	};
 
 	parse_options(fbdev_options, ARRAY_LENGTH(fbdev_options), argc, argv);
+#if !defined(ENABLE_IMXGPU) || !defined(ENABLE_OPENGL) && !defined(ENABLE_IMXG2D)
+	config.use_pixman = 1;
+#elif !defined(ENABLE_OPENGL)
+	config.use_g2d = 1;
+#endif
 
 	config.base.struct_version = WESTON_FBDEV_BACKEND_CONFIG_VERSION;
 	config.base.struct_size = sizeof(struct weston_fbdev_backend_config);
diff --git a/configure.ac b/configure.ac
index 50f8e01..9d98e84 100644
--- a/configure.ac
+++ b/configure.ac
@@ -145,9 +145,33 @@
 AM_CONDITIONAL(ENABLE_EGL, test x$enable_egl = xyes)
 if test x$enable_egl = xyes; then
 	AC_DEFINE([ENABLE_EGL], [1], [Build Weston with EGL support])
-	PKG_CHECK_MODULES(EGL, [egl glesv2])
-        PKG_CHECK_MODULES([EGL_TESTS], [egl glesv2 wayland-client wayland-egl])
+	PKG_CHECK_MODULES(EGL, [egl])
+	PKG_CHECK_MODULES([EGL_TESTS], [egl wayland-client wayland-egl])
 	AC_CHECK_HEADERS([linux/sync_file.h])
+	COMPOSITOR_MODULES="$COMPOSITOR_MODULES egl"
+fi
+
+AC_ARG_ENABLE(opengl, [  --disable-opengl],,
+              enable_opengl=$enable_egl)
+AM_CONDITIONAL(ENABLE_OPENGL, test x$enable_egl = xyes -a x$enable_opengl = xyes)
+if test x$enable_egl = xyes -a x$enable_opengl = xyes; then
+	AC_DEFINE([ENABLE_OPENGL], [1], [Build Weston with OpenGL support])
+	PKG_CHECK_MODULES(OPENGL, [glesv2])
+	PKG_CHECK_MODULES([GL_RENDERER], [libdrm])
+fi
+
+AC_ARG_ENABLE(imxgpu, [  --disable-imxgpu],,
+              enable_imxgpu=yes)
+AM_CONDITIONAL(ENABLE_IMXGPU, test x$enable_imxgpu = xyes)
+if test x$enable_imxgpu = xyes; then
+	AC_DEFINE([ENABLE_IMXGPU], [1], [Build Weston with i.MX GPU driver support])
+fi
+
+AC_ARG_ENABLE(imxg2d, [  --disable-imxg2d],,
+              enable_imxg2d=yes)
+AM_CONDITIONAL(ENABLE_IMXG2D, test x$enable_imxgpu = xyes -a x$enable_imxg2d = xyes)
+if test x$enable_imxgpu = xyes -a x$enable_imxg2d = xyes; then
+	AC_DEFINE([ENABLE_IMXG2D], [1], [Build Weston with i.MX G2D support])
 fi
 
 COMPOSITOR_MODULES="$COMPOSITOR_MODULES xkbcommon >= 0.3.0"
@@ -388,9 +412,9 @@
 AC_ARG_ENABLE(simple-egl-clients,
               AS_HELP_STRING([--disable-simple-egl-clients],
                              [do not build the simple EGL clients]),,
-              enable_simple_egl_clients="$enable_egl")
-AM_CONDITIONAL(BUILD_SIMPLE_EGL_CLIENTS, test "x$enable_simple_egl_clients" = "xyes")
-if test x$enable_simple_egl_clients = xyes; then
+              enable_simple_egl_clients="$enable_opengl")
+AM_CONDITIONAL(BUILD_SIMPLE_EGL_CLIENTS, test "x$enable_simple_egl_clients" = "xyes" -a "x$enable_opengl" = "xyes")
+if test x$enable_simple_egl_clients = xyes -a "x$enable_opengl" = "xyes"; then
   PKG_CHECK_MODULES(SIMPLE_EGL_CLIENT,
                     [egl glesv2 wayland-client wayland-egl wayland-cursor])
 fi
@@ -483,13 +507,13 @@
 fi
 
 AM_CONDITIONAL(HAVE_CAIRO_GLESV2,
-	       [test "x$have_cairo_egl" = "xyes" -a "x$cairo_modules" = "xcairo-glesv2" -a "x$enable_egl" = "xyes"])
+	       [test "x$have_cairo_egl" = "xyes" -a "x$cairo_modules" = "xcairo-glesv2" -a "x$enable_opengl" = "xyes"])
 
 AM_CONDITIONAL(BUILD_FULL_GL_CLIENTS,
-	       test x$cairo_modules = "xcairo-gl" -a "x$have_cairo_egl" = "xyes" -a "x$enable_egl" = "xyes")
+	       test x$cairo_modules = "xcairo-gl" -a "x$have_cairo_egl" = "xyes" -a "x$enable_opengl" = "xyes")
 
 AM_CONDITIONAL(BUILD_SUBSURFACES_CLIENT,
-	       [test '(' "x$have_cairo_egl" != "xyes" -o "x$cairo_modules" = "xcairo-glesv2" ')' -a "x$enable_simple_egl_clients" = "xyes"])
+	       [test '(' "x$have_cairo_egl" != "xyes" -o "x$cairo_modules" = "xcairo-glesv2" ')' -a "x$enable_simple_egl_clients" = "xyes" -a "x$enable_opengl" = "xyes"])
 
 AM_CONDITIONAL(ENABLE_DESKTOP_SHELL, true)
 
@@ -708,6 +732,9 @@
 
 	Cairo Renderer			${with_cairo}
 	EGL				${enable_egl}
+	OpenGL				${enable_opengl}
+	i.MX GPU Drivers		${enable_imxgpu}
+	i.MX G2D Renderer		${enable_imxg2d}
 	xcb_xkb				${have_xcb_xkb}
 	XWayland			${enable_xwayland}
 	dbus				${enable_dbus}
diff --git a/libweston/compositor-drm.h b/libweston/compositor-drm.h
index 9c37c15..960bd1b 100644
--- a/libweston/compositor-drm.h
+++ b/libweston/compositor-drm.h
@@ -67,6 +67,7 @@
 	/** The pixel format to be used by the output. Valid values are:
 	 * - NULL - The format set at backend creation time will be used;
 	 * - "xrgb8888";
+	 * - "argb8888"
 	 * - "rgb565"
 	 * - "xrgb2101010"
 	 */
@@ -104,6 +105,11 @@
 	/** Whether to use the pixman renderer instead of the OpenGL ES renderer. */
 	bool use_pixman;
 
+#if defined(ENABLE_IMXG2D)
+	/** Whether to use the g2d renderer instead of the OpenGL ES renderer. */
+	bool use_g2d;
+#endif
+
 	/** The seat to be used for input and output.
 	 *
 	 * If seat_id is NULL, the seat is taken from XDG_SEAT environment
diff --git a/libweston/compositor-fbdev.c b/libweston/compositor-fbdev.c
index a71b7bd..62f7668 100644
--- a/libweston/compositor-fbdev.c
+++ b/libweston/compositor-fbdev.c
@@ -52,6 +52,18 @@
 #include "libinput-seat.h"
 #include "presentation-time-server-protocol.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 "linux-dmabuf.h"
+#include "linux-dmabuf-unstable-v1-server-protocol.h"
+
 struct fbdev_backend {
 	struct weston_backend base;
 	struct weston_compositor *compositor;
@@ -61,6 +73,15 @@
 	struct udev_input input;
 	uint32_t output_transform;
 	struct wl_listener session_listener;
+	int use_pixman;
+#if defined(ENABLE_IMXGPU)
+	NativeDisplayType display;
+#if defined(ENABLE_IMXG2D)
+	int use_g2d;
+	int clone_mode;
+	char clone_device[50];
+#endif
+#endif
 };
 
 struct fbdev_screeninfo {
@@ -99,8 +120,21 @@
 
 	/* pixman details. */
 	pixman_image_t *hw_surface;
+#if defined(ENABLE_IMXGPU)
+	NativeDisplayType display;
+	NativeWindowType  window;
+#endif
 };
 
+#if defined(ENABLE_IMXGPU)
+#if defined(ENABLE_OPENGL)
+struct gl_renderer_interface *gl_renderer;
+#endif
+#if defined(ENABLE_IMXG2D)
+struct g2d_renderer_interface *g2d_renderer;
+#endif
+#endif
+
 static const char default_seat[] = "seat0";
 
 static inline struct fbdev_head *
@@ -141,8 +175,7 @@
 }
 
 static int
-fbdev_output_repaint(struct weston_output *base, pixman_region32_t *damage,
-		     void *repaint_data)
+fbdev_output_repaint_pixman(struct weston_output *base, pixman_region32_t *damage)
 {
 	struct fbdev_output *output = to_fbdev_output(base);
 	struct weston_compositor *ec = output->base.compositor;
@@ -169,6 +202,27 @@
 }
 
 static int
+fbdev_output_repaint(struct weston_output *base, pixman_region32_t *damage,
+		     void *repaint_data)
+{
+	struct fbdev_output *output = to_fbdev_output(base);
+	struct fbdev_backend *fbb = output->backend;
+	struct weston_compositor *ec = fbb->compositor;
+	if (fbb->use_pixman) {
+		fbdev_output_repaint_pixman(base,damage);
+	} else {
+		ec->renderer->repaint_output(base, damage);
+		/* Update the damage region. */
+		pixman_region32_subtract(&ec->primary_plane.damage,
+	                         &ec->primary_plane.damage, damage);
+		wl_event_source_timer_update(output->finish_frame_timer,
+                                     1000000 / output->mode.refresh);
+	}
+
+	return 0;
+}
+
+static int
 finish_frame_handler(void *data)
 {
 	struct fbdev_output *output = data;
@@ -222,8 +276,9 @@
 	switch(finfo->visual) {
 		case FB_VISUAL_TRUECOLOR:
 		case FB_VISUAL_DIRECTCOLOR:
-			if (vinfo->grayscale != 0)
-				return 0;
+			/* vinfo->grayscale != 0 in 8mqevk board
+				if (vinfo->grayscale != 0)
+				return 0; */
 		break;
 		default:
 			return 0;
@@ -384,14 +439,6 @@
 		return -1;
 	}
 
-	/* Attempt to wake up the framebuffer device, needed for secondary
-	 * framebuffer devices */
-	if (fbdev_set_screen_info(fd, screen_info) < 0) {
-		weston_log("Failed to set mode settings. "
-		           "Attempting to open output anyway.\n");
-	}
-
-
 	return fd;
 }
 
@@ -492,6 +539,7 @@
 }
 
 static void fbdev_output_destroy(struct weston_output *base);
+static int fbdev_output_disable(struct weston_output *base);
 
 static int
 fbdev_output_enable(struct weston_output *base)
@@ -504,24 +552,57 @@
 
 	head = fbdev_output_get_head(output);
 
-	/* Create the frame buffer. */
-	fb_fd = fbdev_frame_buffer_open(head->device, &head->fb_info);
-	if (fb_fd < 0) {
-		weston_log("Creating frame buffer failed.\n");
-		return -1;
-	}
 
-	if (fbdev_frame_buffer_map(output, fb_fd) < 0) {
-		weston_log("Mapping frame buffer failed.\n");
-		return -1;
-	}
 
 	output->base.start_repaint_loop = fbdev_output_start_repaint_loop;
 	output->base.repaint = fbdev_output_repaint;
 
-	if (pixman_renderer_output_create(&output->base,
+	if (backend->use_pixman) {
+		/* Create the frame buffer. */
+		fb_fd = fbdev_frame_buffer_open(head->device, &head->fb_info);
+		if (fb_fd < 0) {
+			weston_log("Creating frame buffer failed.\n");
+			return -1;
+		}
+
+		if (fbdev_frame_buffer_map(output, fb_fd) < 0) {
+			weston_log("Mapping frame buffer failed.\n");
+			return -1;
+		}
+		if (pixman_renderer_output_create(&output->base,
 					PIXMAN_RENDERER_OUTPUT_USE_SHADOW) < 0)
-		goto out_hw_surface;
+			goto out_hw_surface;
+#if defined(ENABLE_IMXGPU)
+#if defined(ENABLE_IMXG2D)
+	} else if (backend->use_g2d) {
+		const char *g2d_device = head->device;
+		if (backend->clone_mode)
+			g2d_device = &(backend->clone_device[0]);
+
+		if (g2d_renderer->fbdev_output_create(&output->base,
+					backend->compositor->wl_display,
+					g2d_device) < 0) {
+			weston_log("g2d_renderer_output_create failed.\n");
+			goto out;
+		}
+#endif
+#if defined(ENABLE_OPENGL)
+	} else {
+		output->window = fbCreateWindow(backend->display, -1, -1, 0, 0);
+		if (output->window == NULL) {
+			fprintf(stderr, "failed to create window\n");
+			return 0;
+		}
+		if (gl_renderer->output_window_create(&output->base,
+						   (EGLNativeWindowType)output->window, (void *)output->window,
+						   gl_renderer->opaque_attribs,
+						   NULL, 0) < 0) {
+			weston_log("gl_renderer_output_create failed.\n");
+			goto out;
+		}
+#endif
+#endif
+	}
 
 	loop = wl_display_get_event_loop(backend->compositor->wl_display);
 	output->finish_frame_timer =
@@ -536,7 +617,7 @@
 
 out_hw_surface:
 	fbdev_frame_buffer_unmap(output);
-
+out:
 	return -1;
 }
 
@@ -544,6 +625,7 @@
 fbdev_output_disable(struct weston_output *base)
 {
 	struct fbdev_output *output = to_fbdev_output(base);
+	struct fbdev_backend *backend = to_fbdev_backend(base->compositor);
 
 	if (!base->enabled)
 		return 0;
@@ -551,9 +633,20 @@
 	wl_event_source_remove(output->finish_frame_timer);
 	output->finish_frame_timer = NULL;
 
-	pixman_renderer_output_destroy(&output->base);
-	fbdev_frame_buffer_unmap(output);
-
+	if (backend->use_pixman) {
+		pixman_renderer_output_destroy(&output->base);
+		fbdev_frame_buffer_unmap(output);
+	}
+#if defined(ENABLE_IMXGPU)
+	if(output->window) {
+		fbDestroyWindow(output->window);
+		output->window = NULL;
+	}
+	if(output->display) {
+		fbDestroyDisplay(output->display);
+		output->display = NULL;
+	}
+#endif
 	return 0;
 }
 
@@ -637,11 +730,27 @@
 fbdev_output_destroy(struct weston_output *base)
 {
 	struct fbdev_output *output = to_fbdev_output(base);
+	struct fbdev_backend *backend = output->backend;
 
 	weston_log("Destroying fbdev output.\n");
 
 	fbdev_output_disable(base);
 
+	if (backend->use_pixman) {
+		if (base->renderer_state != NULL)
+			pixman_renderer_output_destroy(base);
+#if defined(ENABLE_IMXGPU)
+#if defined(ENABLE_IMXG2D)
+	} else if (backend->use_g2d) {
+		g2d_renderer->output_destroy(base);
+#endif
+#if defined(ENABLE_OPENGL)
+	} else {
+		gl_renderer->output_destroy(base);
+#endif
+#endif
+	}
+
 	/* Remove the output. */
 	weston_output_release(&output->base);
 
@@ -705,9 +814,11 @@
 	}
 
 	/* Map the device if it has the same details as before. */
-	if (fbdev_frame_buffer_map(output, fb_fd) < 0) {
-		weston_log("Mapping frame buffer failed.\n");
-		return -1;
+	if (backend->use_pixman) {
+		if (fbdev_frame_buffer_map(output, fb_fd) < 0) {
+			weston_log("Mapping frame buffer failed.\n");
+			return -1;
+		}
 	}
 
 	return 0;
@@ -905,11 +1016,76 @@
 	backend->base.create_output = fbdev_output_create;
 
 	backend->prev_state = WESTON_COMPOSITOR_ACTIVE;
+	backend->use_pixman = param->use_pixman;
+#if defined(ENABLE_IMXGPU) && defined(ENABLE_IMXG2D)
+	backend->use_g2d = param->use_g2d;
+	backend->clone_mode = param->clone_mode;
+	memcpy(&backend->clone_device[0], param->device, strlen(param->device));
+#endif
+	backend->output_transform = param->output_transform;
 
 	weston_setup_vt_switch_bindings(compositor);
 
-	if (pixman_renderer_init(compositor) < 0)
-		goto out_launcher;
+	if (backend->use_pixman) {
+		if (pixman_renderer_init(compositor) < 0)
+			goto out_launcher;
+#if defined(ENABLE_IMXGPU)
+#if defined(ENABLE_IMXG2D)
+	} else if (backend->use_g2d) {
+		g2d_renderer = weston_load_module("g2d-renderer.so",
+						 "g2d_renderer_interface");
+		if (!g2d_renderer) {
+			weston_log("could not load g2d renderer\n");
+			goto out_launcher;
+		}
+
+		if (g2d_renderer->create(backend->compositor) < 0) {
+			weston_log("g2d_renderer_create failed.\n");
+			goto out_launcher;
+		}
+#endif
+#if defined(ENABLE_OPENGL)
+	} else {
+		gl_renderer = weston_load_module("gl-renderer.so",
+						 "gl_renderer_interface");
+		if (!gl_renderer) {
+			weston_log("could not load gl renderer\n");
+			goto out_launcher;
+		}
+
+		/* determine which framebuffer we got so we don't use
+		 * FB_FRAMBUFFER_%d to override default displayId
+		 */
+		int index = -1;
+		sscanf(param->device, "/dev/fb%d", &index);
+
+		if (index < 0) {
+			weston_log("Failed to get proper frambuffer\n");
+			goto out_launcher;
+		}
+
+		backend->display = fbGetDisplayByIndex(index);
+		if (backend->display == NULL) {
+			weston_log("fbGetDisplay failed.\n");
+			goto out_launcher;
+		}
+		if (gl_renderer->display_create(compositor, NO_EGL_PLATFORM,
+					backend->display,
+					NULL,
+					gl_renderer->opaque_attribs,
+					NULL, 0) < 0) {
+			weston_log("gl_renderer_create failed.\n");
+			goto out_launcher;
+		}
+#endif
+#endif
+	}
+
+	if (compositor->renderer->import_dmabuf) {
+		if (linux_dmabuf_setup(compositor) < 0)
+			weston_log("Error: initializing dmabuf "
+				   "support failed.\n");
+	}
 
 	if (!fbdev_head_create(backend, param->device))
 		goto out_launcher;
@@ -940,6 +1116,20 @@
 {
 	config->tty = 0; /* default to current tty */
 	config->device = NULL;
+	config->output_transform = WL_OUTPUT_TRANSFORM_NORMAL;
+#if !defined(ENABLE_IMXGPU) || !defined(ENABLE_OPENGL) && !defined(ENABLE_IMXG2D)
+	config->use_pixman = 1;
+#else
+	config->use_pixman = 0;
+#endif
+#if defined(ENABLE_IMXGPU) && defined(ENABLE_IMXG2D)
+#if !defined(ENABLE_OPENGL)
+	config->use_g2d = 1;
+#else
+	config->use_g2d = 0;
+#endif
+	config->clone_mode = 0;
+#endif
 	config->seat_id = NULL;
 }
 
diff --git a/libweston/compositor-fbdev.h b/libweston/compositor-fbdev.h
index 29c2182..c2ba0d4 100644
--- a/libweston/compositor-fbdev.h
+++ b/libweston/compositor-fbdev.h
@@ -43,6 +43,12 @@
 
 	int tty;
 	char *device;
+	int use_pixman;
+#if defined(ENABLE_IMXG2D)
+	int use_g2d;
+	int clone_mode;
+#endif
+	uint32_t output_transform;
 
 	/** Callback used to configure input devices.
 	 *
diff --git a/libweston/g2d-renderer.c b/libweston/g2d-renderer.c
new file mode 100644
index 0000000..b3618fd
--- /dev/null
+++ b/libweston/g2d-renderer.c
@@ -0,0 +1,1977 @@
+/*
+ * Copyright (c) 2016 Freescale Semiconductor, Inc.
+ * Copyright © 2012 Intel Corporation
+ * Copyright © 2015 Collabora, Ltd.
+ * Copyright 2018 NXP
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define _GNU_SOURCE
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <float.h>
+#include <math.h>
+#include <assert.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <HAL/gc_hal.h>
+#include <drm_fourcc.h>
+
+#include "compositor.h"
+#include "g2d-renderer.h"
+#include "vertex-clipping.h"
+#include "shared/helpers.h"
+#include "linux-dmabuf.h"
+#include "linux-dmabuf-unstable-v1-server-protocol.h"
+
+#define BUFFER_DAMAGE_COUNT 3
+#define ALIGN_TO_16(a) (((a) + 15) & ~15)
+
+static PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display = NULL;
+
+struct wl_viv_buffer
+{
+	struct wl_resource *resource;
+	gcoSURF  surface;
+	gctINT32 width;
+	gctINT32 height;
+	gctINT32 format;
+	gctUINT alignedWidth;
+	gctUINT alignedHeight;
+	gctUINT32 physical[3];
+	gctUINT32 gpuBaseAddr;
+	gceTILING tiling;
+};
+
+typedef struct _g2dRECT
+{
+	int left;
+	int top;
+	int right;
+	int bottom;
+} g2dRECT;
+
+struct fb_screeninfo {
+	struct fb_var_screeninfo varinfo;
+	struct fb_fix_screeninfo fixinfo;
+	unsigned int x_resolution;
+	unsigned int y_resolution;
+	size_t buffer_length; /* length of frame buffer memory in bytes */
+	size_t physical;
+	size_t stride;
+	size_t stride_bytes;
+	enum g2d_format pixel_format; /* frame buffer pixel format */
+	int fb_fd;
+};
+
+struct g2d_output_state {
+	int current_buffer;
+	pixman_region32_t buffer_damage[BUFFER_DAMAGE_COUNT];
+	struct g2d_surfaceEx *renderSurf;
+	int nNumBuffers;
+	int activebuffer;
+	struct g2d_surfaceEx offscreenSurface;
+	struct g2d_buf *offscreen_buf;
+	struct fb_screeninfo fb_info;
+	struct fb_screeninfo *mirror_fb_info;
+	struct g2d_surfaceEx *mirrorSurf;
+	struct g2d_surfaceEx *drm_hw_buffer;
+	int directBlit;
+	int clone_display_num;
+	int width;
+	int height;
+};
+
+struct g2d_surface_state {
+	float color[4];
+	struct weston_buffer_reference buffer_ref;
+	int pitch; /* in pixels */
+	int attached;
+	pixman_region32_t texture_damage;
+	struct g2d_surfaceEx g2d_surface;
+	struct g2d_buf *shm_buf;
+	struct g2d_buf *dma_buf;
+	int shm_buf_length;
+	int bpp;
+
+	struct weston_surface *surface;
+	struct wl_listener surface_destroy_listener;
+	struct wl_listener renderer_destroy_listener;
+};
+
+struct g2d_renderer {
+	struct weston_renderer base;
+	struct wl_signal destroy_signal;
+#ifdef ENABLE_EGL
+	NativeDisplayType display;
+	EGLDisplay egl_display;
+	struct wl_display *wl_display;
+	PFNEGLBINDWAYLANDDISPLAYWL bind_display;
+	PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
+#endif
+	void *handle;
+	int use_drm;
+};
+
+static int
+g2d_renderer_create_surface(struct weston_surface *surface);
+
+static inline struct g2d_surface_state *
+get_surface_state(struct weston_surface *surface)
+{
+	if (!surface->renderer_state)
+		g2d_renderer_create_surface(surface);
+	return (struct g2d_surface_state *)surface->renderer_state;
+}
+
+static inline struct g2d_renderer *
+get_renderer(struct weston_compositor *ec)
+{
+	return (struct g2d_renderer *)ec->renderer;
+}
+
+#define max(a, b) (((a) > (b)) ? (a) : (b))
+#define min(a, b) (((a) > (b)) ? (b) : (a))
+/*
+ * Compute the boundary vertices of the intersection of the global coordinate
+ * aligned rectangle 'rect', and an arbitrary quadrilateral produced from
+ * 'surf_rect' when transformed from surface coordinates into global coordinates.
+ * The vertices are written to 'ex' and 'ey', and the return value is the
+ * number of vertices. Vertices are produced in clockwise winding order.
+ * Guarantees to produce either zero vertices, or 3-8 vertices with non-zero
+ * polygon area.
+ */
+static int
+calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
+		pixman_box32_t *surf_rect, float *ex, float *ey)
+{
+
+	struct clip_context ctx;
+	int i, n;
+	float min_x, max_x, min_y, max_y;
+	struct polygon8 surf = {
+		{ surf_rect->x1, surf_rect->x2, surf_rect->x2, surf_rect->x1 },
+		{ surf_rect->y1, surf_rect->y1, surf_rect->y2, surf_rect->y2 },
+		4
+	};
+
+	ctx.clip.x1 = rect->x1;
+	ctx.clip.y1 = rect->y1;
+	ctx.clip.x2 = rect->x2;
+	ctx.clip.y2 = rect->y2;
+
+	/* transform surface to screen space: */
+	for (i = 0; i < surf.n; i++)
+		weston_view_to_global_float(ev, surf.x[i], surf.y[i],
+						&surf.x[i], &surf.y[i]);
+
+	/* find bounding box: */
+	min_x = max_x = surf.x[0];
+	min_y = max_y = surf.y[0];
+
+	for (i = 1; i < surf.n; i++) {
+		min_x = min(min_x, surf.x[i]);
+		max_x = max(max_x, surf.x[i]);
+		min_y = min(min_y, surf.y[i]);
+		max_y = max(max_y, surf.y[i]);
+	}
+
+	/* First, simple bounding box check to discard early transformed
+	 * surface rects that do not intersect with the clip region:
+	 */
+	if ((min_x >= ctx.clip.x2) || (max_x <= ctx.clip.x1) ||
+		(min_y >= ctx.clip.y2) || (max_y <= ctx.clip.y1))
+		return 0;
+
+	/* Simple case, bounding box edges are parallel to surface edges,
+	 * there will be only four edges.  We just need to clip the surface
+	 * vertices to the clip rect bounds:
+	 */
+	if (!ev->transform.enabled)
+		return clip_simple(&ctx, &surf, ex, ey);
+
+	/* Transformed case: use a general polygon clipping algorithm to
+	 * clip the surface rectangle with each side of 'rect'.
+	 * The algorithm is Sutherland-Hodgman, as explained in
+	 * http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c8965/Polygon-Clipping.htm
+	 * but without looking at any of that code.
+	 */
+	n = clip_transformed(&ctx, &surf, ex, ey);
+
+	if (n < 3)
+		return 0;
+
+	return n;
+}
+
+static void
+calculate_rect_with_transform(int surfaceWidth, int surfaceHeight,
+				  uint32_t transform, g2dRECT *rect)
+{
+	g2dRECT tmp = *rect;
+
+	switch (transform) {
+	case WL_OUTPUT_TRANSFORM_NORMAL:
+	default:
+		break;
+	case WL_OUTPUT_TRANSFORM_90:
+		rect->right = surfaceWidth - tmp.top;
+		rect->left = rect->right - (tmp.bottom - tmp.top);
+		rect->top = tmp.left;
+		rect->bottom = rect->top + (tmp.right - tmp.left);
+		break;
+	case WL_OUTPUT_TRANSFORM_270:
+		rect->left = tmp.top;
+		rect->right = rect->left + (tmp.bottom - tmp.top);
+		rect->bottom = surfaceHeight - tmp.left;
+		rect->top = rect->bottom - (tmp.right - tmp.left);
+		break;
+	case WL_OUTPUT_TRANSFORM_180:
+		rect->left = surfaceWidth - tmp.right;
+		rect->right = rect->left + (tmp.right - tmp.left);
+		rect->bottom = surfaceHeight - tmp.top;
+		rect->top = rect->bottom - (tmp.bottom - tmp.top);
+		break;
+	}
+}
+
+static enum g2d_rotation
+convert_transform_to_rot(uint32_t transform)
+{
+	enum g2d_rotation rot;
+	switch(transform) {
+	case WL_OUTPUT_TRANSFORM_NORMAL:
+	default:
+		rot = G2D_ROTATION_0;
+		break;
+	case WL_OUTPUT_TRANSFORM_90:
+		/*For source rotation*/
+		rot = G2D_ROTATION_270;
+		break;
+	case WL_OUTPUT_TRANSFORM_270:
+		rot = G2D_ROTATION_90;
+		break;
+	case WL_OUTPUT_TRANSFORM_180:
+		rot = G2D_ROTATION_180;
+		break;
+	}
+	return rot;
+}
+
+static inline struct g2d_output_state *
+get_output_state(struct weston_output *output)
+{
+	return (struct g2d_output_state *)output->renderer_state;
+}
+
+static void
+g2d_getG2dTiling(IN gceTILING tiling, enum g2d_tiling* g2dTiling)
+{
+	switch(tiling)
+	{
+	case gcvLINEAR:
+		*g2dTiling = G2D_LINEAR;
+		break;
+	case gcvTILED:
+		*g2dTiling = G2D_TILED;
+		break;
+	case gcvSUPERTILED:
+		*g2dTiling = G2D_SUPERTILED;
+		break;
+	default:
+		weston_log("Error in function %s\n", __func__);
+		break;
+	}
+}
+
+static void
+g2d_getG2dFormat(IN gceSURF_FORMAT Format, enum g2d_format* g2dFormat)
+{
+	switch(Format)
+	{
+	case gcvSURF_R5G6B5:
+		*g2dFormat = G2D_RGB565;
+		break;
+	case gcvSURF_A8B8G8R8:
+		*g2dFormat = G2D_RGBA8888;
+		break;
+	case gcvSURF_X8B8G8R8:
+		*g2dFormat = G2D_RGBA8888;
+		break;
+	case gcvSURF_A8R8G8B8:
+		*g2dFormat = G2D_BGRA8888;
+		break;
+	case gcvSURF_X8R8G8B8:
+		*g2dFormat = G2D_BGRX8888;
+		break;
+	case gcvSURF_B5G6R5:
+		*g2dFormat = G2D_BGR565;
+		break;
+	case gcvSURF_B8G8R8A8:
+		*g2dFormat = G2D_ARGB8888;
+		break;
+	case gcvSURF_R8G8B8A8:
+		*g2dFormat = G2D_ABGR8888;
+		break;
+	case gcvSURF_B8G8R8X8:
+		*g2dFormat = G2D_XRGB8888;
+		break;
+	case gcvSURF_R8G8B8X8:
+		*g2dFormat = G2D_XBGR8888;
+		break;
+	case gcvSURF_NV12:
+		*g2dFormat = G2D_NV12;
+		break;
+	case gcvSURF_NV21:
+		*g2dFormat = G2D_NV21;
+		break;
+	case gcvSURF_I420:
+		*g2dFormat = G2D_I420;
+		break;
+	case gcvSURF_YV12:
+		*g2dFormat = G2D_YV12;
+		break;
+	case gcvSURF_YUY2:
+		*g2dFormat = G2D_YUYV;
+		break;
+	case gcvSURF_YVYU:
+		*g2dFormat = G2D_YVYU;
+		break;
+	case gcvSURF_UYVY:
+		*g2dFormat = G2D_UYVY;
+		break;
+	case gcvSURF_VYUY:
+		*g2dFormat = G2D_VYUY;
+		break;
+	case gcvSURF_NV16:
+		*g2dFormat = G2D_NV16;
+		break;
+	case gcvSURF_NV61:
+		*g2dFormat = G2D_NV61;
+		break;
+	default:
+		weston_log("Error in function %s, Format not supported\n", __func__);
+		break;
+	}
+}
+
+static void printG2dSurfaceInfo(struct g2d_surfaceEx* g2dSurface, const char* msg)
+{
+	weston_log("%s physicAddr = %x left = %d right = %d top=%d bottom=%d stride= %d tiling = %d, format=%d \n",
+				msg,
+				g2dSurface->base.planes[0],
+				g2dSurface->base.left,
+				g2dSurface->base.right,
+				g2dSurface->base.top,
+				g2dSurface->base.bottom,
+				g2dSurface->base.stride,
+				g2dSurface->tiling,
+				g2dSurface->base.format);
+}
+
+static void
+get_g2dSurface(struct wl_viv_buffer *buffer, struct g2d_surfaceEx *g2dSurface)
+{
+	if(buffer->width < 0 || buffer->height < 0)
+	{
+		weston_log("invalid EGL buffer in function %s\n", __func__);
+		return;
+	}
+	g2d_getG2dFormat(buffer->format, &g2dSurface->base.format);
+	g2d_getG2dTiling(buffer->tiling, &g2dSurface->tiling);
+	g2dSurface->base.planes[0] = buffer->physical[0] + buffer->gpuBaseAddr;
+	g2dSurface->base.planes[1] = buffer->physical[1] + buffer->gpuBaseAddr;
+	g2dSurface->base.planes[2] = buffer->physical[2] + buffer->gpuBaseAddr;
+	g2dSurface->base.left = 0;
+	g2dSurface->base.top = 0;
+	g2dSurface->base.right = buffer->width;
+	g2dSurface->base.bottom = buffer->height;
+	g2dSurface->base.stride = buffer->alignedWidth;
+	g2dSurface->base.width	= buffer->width;
+	g2dSurface->base.height = buffer->height;
+	g2dSurface->base.rot	= G2D_ROTATION_0;
+}
+
+static void
+g2d_SetSurfaceRect(struct g2d_surfaceEx* g2dSurface, g2dRECT* rect)
+{
+	if(g2dSurface && rect)
+	{
+		g2dSurface->base.left	= rect->left;
+		g2dSurface->base.top	= rect->top;
+		g2dSurface->base.right	= rect->right;
+		g2dSurface->base.bottom = rect->bottom;
+	}
+}
+
+#define _hasAlpha(format) (format==G2D_RGBA8888 || format==G2D_BGRA8888 \
+	|| format==G2D_ARGB8888 || format==G2D_ABGR8888)
+
+static int
+g2d_blit_surface(void *handle, struct g2d_surfaceEx * srcG2dSurface, struct g2d_surfaceEx *dstG2dSurface,
+	g2dRECT *srcRect, g2dRECT *dstRect)
+{
+	g2d_SetSurfaceRect(srcG2dSurface, srcRect);
+	g2d_SetSurfaceRect(dstG2dSurface, dstRect);
+	srcG2dSurface->base.blendfunc = G2D_ONE;
+	dstG2dSurface->base.blendfunc = G2D_ONE_MINUS_SRC_ALPHA;
+	if(!(_hasAlpha(srcG2dSurface->base.format)))
+	{
+		g2d_disable(handle, G2D_BLEND);
+	}
+
+	if(g2d_blitEx(handle, srcG2dSurface, dstG2dSurface))
+	{
+		printG2dSurfaceInfo(srcG2dSurface, "SRC:");
+		printG2dSurfaceInfo(dstG2dSurface, "DST:");
+		return -1;
+	}
+	return 0;
+}
+
+static void
+g2d_flip_surface(struct weston_output *output)
+{
+	struct g2d_output_state *go = get_output_state(output);
+	go->fb_info.varinfo.yoffset  = go->activebuffer * go->fb_info.y_resolution;
+
+	if(ioctl(go->fb_info.fb_fd, FBIOPAN_DISPLAY, &(go->fb_info.varinfo)) < 0)
+	{
+		weston_log("FBIOPAN_DISPLAY Failed\n");
+	}
+	go->activebuffer = (go->activebuffer + 1)  % go->nNumBuffers;
+}
+
+static void
+copy_to_framebuffer(struct weston_output *output)
+{
+	struct g2d_renderer *gr = get_renderer(output->compositor);
+	struct g2d_output_state *go = get_output_state(output);
+	g2dRECT clipRect = {0};
+
+	if((!go->directBlit && go->nNumBuffers == 1) || (go->clone_display_num))
+	{
+		clipRect.left	= output->previous_damage.extents.x1;
+		clipRect.top	= output->previous_damage.extents.y1;
+		clipRect.right	= output->previous_damage.extents.x2;
+		clipRect.bottom = output->previous_damage.extents.y2;
+
+		if(clipRect.left >= go->offscreenSurface.base.width)
+		{
+			clipRect.left -= go->offscreenSurface.base.width;
+			clipRect.right -= go->offscreenSurface.base.width;
+		}
+	}
+
+	if(!go->directBlit && go->nNumBuffers == 1)
+	{
+		g2dRECT srcRect  = {0, 0, go->offscreenSurface.base.width, go->offscreenSurface.base.height};
+		g2dRECT dstrect  = srcRect;
+		clipRect = srcRect;
+		g2d_set_clipping(gr->handle, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
+		g2d_blit_surface(gr->handle, &go->offscreenSurface,
+			&go->renderSurf[go->activebuffer], &srcRect, &dstrect);
+	}
+
+	if(go->clone_display_num)
+	{
+		int i = 0;
+		for(i = 0; i < go->clone_display_num; i++)
+		{
+			g2dRECT srcRect  = {0, 0, go->renderSurf[go->activebuffer].base.width, go->renderSurf[go->activebuffer].base.height};
+			g2dRECT dstrect  = {0, 0, go->mirrorSurf[i].base.width, go->mirrorSurf[i].base.height};
+			if(go->directBlit || go->nNumBuffers > 1)
+			{
+				g2d_blit_surface(gr->handle, &go->renderSurf[go->activebuffer],
+				&go->mirrorSurf[i], &srcRect, &dstrect);
+			}
+			else
+			{
+				g2d_blit_surface(gr->handle, &go->offscreenSurface,
+					&go->mirrorSurf[i], &srcRect, &dstrect);
+			}
+		}
+	}
+
+	g2d_finish(gr->handle);
+
+	if(go->nNumBuffers > 1)
+	{
+		g2d_flip_surface(output);
+	}
+}
+
+static int
+is_view_visible(struct weston_view *view)
+{
+	/* Return false, if surface is guaranteed to be totally obscured. */
+	int ret;
+	pixman_region32_t unocc;
+
+	pixman_region32_init(&unocc);
+	pixman_region32_subtract(&unocc, &view->transform.boundingbox,
+				 &view->clip);
+	ret = pixman_region32_not_empty(&unocc);
+	pixman_region32_fini(&unocc);
+
+	return ret;
+}
+ 
+static void
+use_output(struct weston_output *output)
+{
+	struct weston_compositor *compositor = output->compositor;
+	struct weston_view *view;
+	struct g2d_output_state *go = get_output_state(output);
+	int visibleViews=0;
+	int fullscreenViews=0;
+
+	if(go->nNumBuffers == 1)
+	{
+		wl_list_for_each_reverse(view, &compositor->view_list, link)
+			if (view->plane == &compositor->primary_plane && is_view_visible(view))
+			{
+				visibleViews++;
+				if(view->surface->width == go->width && view->surface->height == go->height)
+				{
+					pixman_box32_t *bb_rects;
+					int nbb=0;
+					bb_rects = pixman_region32_rectangles(&view->transform.boundingbox, &nbb);
+					if(nbb == 1)
+						if(bb_rects[0].x1 == 0 && bb_rects[0].y1 ==0)
+							fullscreenViews++;
+				}
+			}
+
+		go->directBlit = ((visibleViews == 1) || (fullscreenViews > 1));
+	}
+}
+
+static void
+g2d_clip_rects(enum wl_output_transform transform,
+			g2dRECT *srcRect,
+			g2dRECT *dstrect,
+			int dstWidth,
+			int dstHeight)
+{
+	int srcWidth = srcRect->right - srcRect->left;
+	int srcHeight = srcRect->bottom - srcRect->top;
+	float scale_v = 1.0f;
+	float scale_h = 1.0f;
+
+	if(transform == WL_OUTPUT_TRANSFORM_90
+		|| transform == WL_OUTPUT_TRANSFORM_270)
+	{
+		scale_h = (float)srcHeight / (dstrect->right - dstrect->left);
+		scale_v = (float)srcWidth / (dstrect->bottom - dstrect->top);
+	}
+	else
+	{
+		scale_h = (float)srcWidth / (dstrect->right - dstrect->left);
+		scale_v = (float)srcHeight / (dstrect->bottom - dstrect->top);
+	}
+	switch (transform) {
+	case WL_OUTPUT_TRANSFORM_NORMAL:
+		if(dstrect->left < 0)
+		{
+			srcRect->left += floorf((float)(-dstrect->left) * scale_h);
+			dstrect->left = 0;
+			if(srcRect->left >= srcRect->right)
+				return;
+		}
+		if(dstrect->right > dstWidth)
+		{
+			srcRect->right -= floorf((float)(dstrect->right - dstWidth) * scale_h);
+			dstrect->right = dstWidth;
+			if(srcRect->right <= srcRect->left)
+				return;
+		}
+		if(dstrect->top < 0)
+		{
+			srcRect->top += floorf((float)(-dstrect->top) * scale_v);
+			dstrect->top = 0;
+			if(srcRect->top <= srcRect->bottom)
+				return;
+		}
+		if(dstrect->bottom > dstHeight)
+		{
+			srcRect->bottom -= floorf((float)(dstrect->bottom - dstHeight) * scale_v);
+			dstrect->bottom = dstHeight;
+			if(srcRect->bottom < 0)
+				return;
+		}
+		break;
+	case WL_OUTPUT_TRANSFORM_90:
+		if(dstrect->left < 0)
+		{
+			srcRect->bottom -= floorf((float)(-dstrect->left) * scale_h);
+			dstrect->left = 0;
+			if(srcRect->top >= srcRect->bottom)
+					return;
+		}
+		if(dstrect->bottom > dstHeight)
+		{
+			srcRect->right -= floorf((float)(dstrect->bottom - dstHeight) * scale_v);
+			dstrect->bottom = dstHeight;
+			if(srcRect->right < 0)
+				return;
+		}
+		if(dstrect->top < 0)
+		{
+			srcRect->left += floorf((float)(-dstrect->top) * scale_h);
+			dstrect->top = 0;
+			if(srcRect->left > srcRect->right)
+				return;
+		}
+		break;
+	case WL_OUTPUT_TRANSFORM_270:
+		if(dstrect->left < 0)
+		{
+			srcRect->top += floorf((float)(-dstrect->left) * scale_h);
+			dstrect->left = 0;
+			if(srcRect->top >= srcRect->bottom)
+					return;
+		}
+		if(dstrect->top < 0)
+		{
+			srcRect->right -= floorf((float)(-dstrect->top) * scale_v);
+			dstrect->top = 0;
+			if(srcRect->left >= srcRect->right)
+				return;
+		}
+		if(dstrect->bottom > dstHeight)
+		{
+			srcRect->left += floorf((float)(dstrect->bottom - dstHeight) * scale_v);
+			dstrect->bottom = dstHeight;
+			if(srcRect->right <= srcRect->left)
+				return;
+		}
+		if(dstrect->right > dstWidth)
+		{
+			srcRect->bottom -= floorf((float)(dstrect->right - dstWidth) * scale_h);
+			dstrect->right = dstWidth;
+			if(srcRect->bottom <= srcRect->top)
+				return;
+		}
+		break;
+	case WL_OUTPUT_TRANSFORM_180:
+		if(dstrect->left < 0)
+		{
+			srcRect->right -= floorf((float)(-dstrect->left) * scale_h);
+			dstrect->left = 0;
+			if(srcRect->left >= srcRect->right)
+					return;
+		}
+		if(dstrect->right > dstWidth)
+		{
+			srcRect->left += floorf((float)(dstrect->right - dstWidth) * scale_h);
+			dstrect->right = dstWidth;
+			if(srcRect->right <= srcRect->left)
+				return;
+		}
+		if(dstrect->top < 0)
+		{
+			srcRect->bottom -= floorf((float)(-dstrect->top) * scale_v);
+			dstrect->top = 0;
+			if(srcRect->top >= srcRect->bottom)
+				return;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static int
+g2d_renderer_read_pixels(struct weston_output *output,
+				   pixman_format_code_t format, void *pixels,
+				   uint32_t x, uint32_t y,
+				   uint32_t width, uint32_t height)
+{
+	return 0;
+}
+
+static int g2d_int_from_double(double d)
+{
+	return wl_fixed_to_int(wl_fixed_from_double(d));
+}
+
+static void
+repaint_region(struct weston_view *ev, struct weston_output *output, struct g2d_output_state *go, pixman_region32_t *region,
+		pixman_region32_t *surf_region){
+
+	struct g2d_renderer *gr = get_renderer(ev->surface->compositor);
+	struct g2d_surface_state *gs = get_surface_state(ev->surface);
+
+	pixman_box32_t *rects, *surf_rects, *bb_rects;
+	int i, j, nrects, nsurf, nbb=0;
+	g2dRECT srcRect = {0};
+	g2dRECT dstrect = {0};
+	g2dRECT clipRect = {0};
+	int dstWidth = 0;
+	int dstHeight = 0;
+	struct g2d_surfaceEx *dstsurface;
+	struct g2d_surfaceEx srcsurface = gs->g2d_surface;
+	uint32_t view_transform = ev->surface->buffer_viewport.buffer.transform;
+	int src_x = wl_fixed_to_int (ev->surface->buffer_viewport.buffer.src_x);
+	int src_y = wl_fixed_to_int (ev->surface->buffer_viewport.buffer.src_y);
+	int src_width = wl_fixed_to_int (ev->surface->buffer_viewport.buffer.src_width);
+	int src_height = wl_fixed_to_int (ev->surface->buffer_viewport.buffer.src_height);
+	int scale = ev->surface->buffer_viewport.buffer.scale;
+	if (ev->alpha < 1.0) {
+		/* Skip the render for global alpha, a workaround to disable the
+		   fade effect, it created garbage info in the sequence test.*/
+		return;
+	}
+
+	bb_rects = pixman_region32_rectangles(&ev->transform.boundingbox, &nbb);
+
+	if(!gs->attached || nbb <= 0)
+	{
+		return;
+	}
+
+	rects = pixman_region32_rectangles(region, &nrects);
+	surf_rects = pixman_region32_rectangles(surf_region, &nsurf);
+	if(src_width != -1 && src_width > 0 && src_x >=0 && src_y >= 0
+		&& src_x < gs->g2d_surface.base.width
+		&& src_y < gs->g2d_surface.base.height)
+	{
+		srcRect.left = src_x * scale;
+		srcRect.top = src_y * scale;
+		srcRect.right = min (gs->g2d_surface.base.width, (src_x + src_width) * scale);
+		srcRect.bottom = min (gs->g2d_surface.base.height, (src_y + src_height) * scale);
+	}
+	else
+	{
+		srcRect.left = srcsurface.base.left;
+		srcRect.top  = srcsurface.base.top;
+		srcRect.right  = srcsurface.base.right;
+		srcRect.bottom = srcsurface.base.bottom;
+	}
+	if(go->drm_hw_buffer && gr->use_drm)
+	{
+		dstsurface = go->drm_hw_buffer;
+	}
+	else
+	{
+		if(go->nNumBuffers > 1 || go->directBlit)
+		{
+			dstsurface = &go->renderSurf[go->activebuffer];
+		}
+		else
+		{
+			dstsurface = &go->offscreenSurface;
+		}
+	}
+	dstWidth  = dstsurface->base.width;
+	dstHeight = dstsurface->base.height;
+	/*Calculate the destrect once for all*/
+	dstrect.left = bb_rects[0].x1;
+	dstrect.top = bb_rects[0].y1;
+	dstrect.right = bb_rects[0].x2;
+	dstrect.bottom = bb_rects[0].y2;
+	/*Multi display support*/
+	if(output->x > 0)
+	{
+		dstrect.left = dstrect.left - output->x;
+		dstrect.right = dstrect.right - output->x;
+	}
+
+	calculate_rect_with_transform(dstsurface->base.width,
+					  dstsurface->base.height,
+					  output->transform, &dstrect);
+
+	if(view_transform != output->transform)
+	{
+		g2d_clip_rects(output->transform, &srcRect, &dstrect, dstWidth, dstHeight);
+		srcsurface.base.rot = convert_transform_to_rot(output->transform);
+	} else {
+		/* if the view is transformed by compositor, we only need handle input crop
+		 * according to dst rect */
+		g2d_clip_rects(WL_OUTPUT_TRANSFORM_NORMAL, &srcRect, &dstrect, dstWidth, dstHeight);
+	}
+
+	for (i = 0; i < nrects; i++)
+	{
+		pixman_box32_t *rect = &rects[i];
+		gctFLOAT min_x, max_x, min_y, max_y;
+
+		for (j = 0; j < nsurf; j++)
+		{
+			pixman_box32_t *surf_rect = &surf_rects[j];
+			gctFLOAT ex[8], ey[8];			/* edge points in screen space */
+			int n;
+			int m=0;
+			n = calculate_edges(ev, rect, surf_rect, ex, ey);
+			if (n < 3)
+				continue;
+
+			min_x = max_x = ex[0];
+			min_y = max_y = ey[0];
+			for (m = 1; m < n; m++)
+			{
+				min_x = min(min_x, ex[m]);
+				max_x = max(max_x, ex[m]);
+				min_y = min(min_y, ey[m]);
+				max_y = max(max_y, ey[m]);
+			}
+
+			clipRect.left = g2d_int_from_double(min_x);
+			clipRect.top = g2d_int_from_double(min_y);
+			clipRect.right = g2d_int_from_double(max_x);
+			clipRect.bottom = g2d_int_from_double(max_y);
+
+			if(output->x > 0)
+			{
+				clipRect.left = clipRect.left - output->x;
+				clipRect.right = clipRect.right - output->x;
+			}
+			/* Need compute the clip rect with transform */
+			calculate_rect_with_transform(dstsurface->base.width,
+							  dstsurface->base.height,
+							  output->transform, &clipRect);
+			if(clipRect.left >= clipRect.right || clipRect.top >= clipRect.bottom)
+			{
+				return;
+			}
+			g2d_set_clipping(gr->handle, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
+			g2d_blit_surface(gr->handle, &srcsurface, dstsurface, &srcRect, &dstrect);
+		}
+	}
+}
+
+static void
+draw_view(struct weston_view *ev, struct weston_output *output,
+		 pixman_region32_t *damage) /* in global coordinates */
+{
+	struct weston_compositor *ec = ev->surface->compositor;	
+	struct g2d_output_state *go = get_output_state(output);
+	struct g2d_surface_state *gs = get_surface_state(ev->surface);
+	struct g2d_renderer *gr = get_renderer(ec);
+	/* repaint bounding region in global coordinates: */
+	pixman_region32_t repaint;
+	/* opaque region in surface coordinates: */
+	pixman_region32_t surface_opaque;
+	/* non-opaque region in surface coordinates: */
+	pixman_region32_t surface_blend;
+
+	pixman_region32_init(&repaint);
+	pixman_region32_intersect(&repaint,
+				  &ev->transform.boundingbox, damage);
+	pixman_region32_subtract(&repaint, &repaint, &ev->clip);
+
+	if (!pixman_region32_not_empty(&repaint))
+		goto out;
+
+	/* blended region is whole surface minus opaque region: */
+	pixman_region32_init_rect(&surface_blend, 0, 0,
+				  ev->surface->width, ev->surface->height);
+	if (ev->geometry.scissor_enabled)
+		pixman_region32_intersect(&surface_blend, &surface_blend,
+					  &ev->geometry.scissor);
+	pixman_region32_subtract(&surface_blend, &surface_blend,
+				 &ev->surface->opaque);
+
+	/* XXX: Should we be using ev->transform.opaque here? */
+	pixman_region32_init(&surface_opaque);
+	if (ev->geometry.scissor_enabled)
+		pixman_region32_intersect(&surface_opaque,
+					  &ev->surface->opaque,
+					  &ev->geometry.scissor);
+	else
+		pixman_region32_copy(&surface_opaque, &ev->surface->opaque);
+
+	if (pixman_region32_not_empty(&surface_opaque)) {
+		if (ev->alpha < 1.0) {
+			g2d_enable(gr->handle, G2D_BLEND);
+			g2d_enable(gr->handle, G2D_GLOBAL_ALPHA);
+			gs->g2d_surface.base.global_alpha = ev->alpha * 0xFF;
+		}
+		repaint_region(ev, output, go, &repaint, &surface_opaque);
+		g2d_disable(gr->handle, G2D_GLOBAL_ALPHA);
+		g2d_disable(gr->handle, G2D_BLEND);
+	}
+
+	if (pixman_region32_not_empty(&surface_blend)) {
+		g2d_enable(gr->handle, G2D_BLEND);
+		if (ev->alpha < 1.0) {
+			g2d_enable(gr->handle, G2D_GLOBAL_ALPHA);
+			gs->g2d_surface.base.global_alpha = ev->alpha * 0xFF;
+		}
+		repaint_region(ev, output, go, &repaint, &surface_blend);
+		g2d_disable(gr->handle, G2D_GLOBAL_ALPHA);
+		g2d_disable(gr->handle, G2D_BLEND);
+	}
+	pixman_region32_fini(&surface_blend);
+	pixman_region32_fini(&surface_opaque);
+
+out:
+	pixman_region32_fini(&repaint);
+}
+
+static void
+repaint_views(struct weston_output *output, pixman_region32_t *damage)
+{
+	struct weston_compositor *compositor = output->compositor;
+	struct weston_view *view;
+
+	wl_list_for_each_reverse(view, &compositor->view_list, link)
+		if (view->plane == &compositor->primary_plane)
+			draw_view(view, output, damage);
+}
+
+static void
+output_get_damage(struct weston_output *output,
+		  pixman_region32_t *buffer_damage)
+{
+	struct g2d_output_state *go = get_output_state(output);
+	int i;
+
+	for (i = 0; i < BUFFER_DAMAGE_COUNT; i++)
+		pixman_region32_union(buffer_damage,
+			buffer_damage,
+			&go->buffer_damage[i]);
+}
+
+static void
+output_rotate_damage(struct weston_output *output,
+			 pixman_region32_t *output_damage)
+{
+	struct g2d_output_state *go = get_output_state(output);
+
+	go->current_buffer = (go->current_buffer + 1) % BUFFER_DAMAGE_COUNT;
+
+	pixman_region32_copy(&go->buffer_damage[go->current_buffer], output_damage);
+}
+
+static void
+g2d_renderer_repaint_output(struct weston_output *output,
+				 pixman_region32_t *output_damage)
+{
+	struct weston_compositor *compositor = output->compositor;
+	struct g2d_renderer *gr = get_renderer(compositor);
+	pixman_region32_t buffer_damage, total_damage;
+
+	use_output(output);
+
+	pixman_region32_init(&total_damage);
+	pixman_region32_init(&buffer_damage);
+
+	output_get_damage(output, &buffer_damage);
+	output_rotate_damage(output, output_damage);
+	pixman_region32_union(&total_damage, &buffer_damage, output_damage);
+
+	repaint_views(output, &total_damage);
+
+	pixman_region32_fini(&total_damage);
+	pixman_region32_fini(&buffer_damage);
+
+	g2d_finish(gr->handle);
+
+	pixman_region32_copy(&output->previous_damage, output_damage);
+	wl_signal_emit(&output->frame_signal, output);
+	if(!gr->use_drm)
+		copy_to_framebuffer(output);
+}
+
+static void
+g2d_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer)
+{
+	struct wl_viv_buffer *vivBuffer = wl_resource_get_user_data(buffer->resource);
+	struct g2d_surface_state *gs = get_surface_state(es);
+	buffer->width = vivBuffer->width;
+	buffer->height = vivBuffer->height;
+	get_g2dSurface(vivBuffer, &gs->g2d_surface);
+}
+
+static void
+g2d_renderer_copy_shm_buffer(struct g2d_surface_state *gs, struct weston_buffer *buffer)
+{
+	int alignedWidth = ALIGN_TO_16(buffer->width);
+	int height = 0;
+	uint8_t *src = wl_shm_buffer_get_data(buffer->shm_buffer);
+	uint8_t *dst = gs->shm_buf->buf_vaddr;
+	int bpp = gs->bpp;
+	int plane_size[3] = {0,};
+	int src_plane_offset[3] = {0,};
+	int dst_plane_offset[3] = {0,};
+	int uv_src_stride = 0;
+	int uv_dst_stride = 0;
+	int n_planes = 0;
+	int i, j;
+
+	switch (wl_shm_buffer_get_format(buffer->shm_buffer)) {
+		case WL_SHM_FORMAT_XRGB8888:
+		case WL_SHM_FORMAT_ARGB8888:
+		case WL_SHM_FORMAT_RGB565:
+			n_planes = 1;
+			height = buffer->height;
+			plane_size[0] = wl_shm_buffer_get_stride(buffer->shm_buffer)*buffer->height;
+			break;
+		case WL_SHM_FORMAT_YUYV:
+			n_planes = 1;
+			height = ALIGN_TO_16(buffer->height);
+			plane_size[0] = wl_shm_buffer_get_stride(buffer->shm_buffer)*buffer->height;
+			break;
+		case WL_SHM_FORMAT_NV12:
+			n_planes = 2;
+			height = ALIGN_TO_16(buffer->height);
+			plane_size[0] = wl_shm_buffer_get_stride(buffer->shm_buffer)*buffer->height;
+			plane_size[1] = wl_shm_buffer_get_stride(buffer->shm_buffer)*buffer->height / 2;
+			src_plane_offset[1] = plane_size[0];
+			dst_plane_offset[1] = alignedWidth * height;
+			uv_src_stride = wl_shm_buffer_get_stride(buffer->shm_buffer);
+			uv_dst_stride = alignedWidth;
+			break;
+		case WL_SHM_FORMAT_YUV420:
+			n_planes = 3;
+			height = ALIGN_TO_16(buffer->height);
+			plane_size[0] = wl_shm_buffer_get_stride(buffer->shm_buffer)*buffer->height;
+			plane_size[1] = wl_shm_buffer_get_stride(buffer->shm_buffer)*buffer->height / 4;
+			plane_size[2] = plane_size[1];
+			src_plane_offset[1] = plane_size[0];
+			src_plane_offset[2] = plane_size[0] + plane_size[1];
+			dst_plane_offset[1] = alignedWidth * height;
+			dst_plane_offset[2] = dst_plane_offset[1] + alignedWidth * height / 4;
+			uv_src_stride = wl_shm_buffer_get_stride(buffer->shm_buffer) / 2;
+			uv_dst_stride = alignedWidth / 2;
+			break;
+		default:
+			weston_log("warning: copy shm buffer meet unknown format: %08x\n",
+				   wl_shm_buffer_get_format(buffer->shm_buffer));
+			return;
+	}
+
+	wl_shm_buffer_begin_access(buffer->shm_buffer);
+	if(alignedWidth == buffer->width && height == buffer->height)
+	{
+		for (i = 0; i < n_planes; i++)
+			memcpy (dst + dst_plane_offset[i], src + src_plane_offset[i], plane_size[i]);
+	}
+	else
+	{
+		int src_stride = wl_shm_buffer_get_stride(buffer->shm_buffer);
+		int dst_stride = alignedWidth * bpp;
+		/* copy the 1st plane */
+		for (i = 0; i < buffer->height; i++)
+		{
+			memcpy(dst + dst_plane_offset[0] + dst_stride * i, src + src_plane_offset[0] + src_stride * i, src_stride);
+		}
+		/* copy the rest plane */
+		for (i = 1; i < n_planes; i++)
+		{
+			for (j = 0; j < buffer->height / 2; j++)
+			{
+				memcpy(dst + dst_plane_offset[i] + uv_dst_stride * j, src + src_plane_offset[i] + uv_src_stride * j, uv_src_stride);
+			}
+		}
+	}
+	wl_shm_buffer_end_access(buffer->shm_buffer);
+}
+
+static void
+g2d_renderer_flush_damage(struct weston_surface *surface)
+{
+	struct g2d_surface_state *gs = get_surface_state(surface);
+	struct weston_buffer *buffer = gs->buffer_ref.buffer;
+	struct weston_view *view;
+	int texture_used;
+	pixman_region32_union(&gs->texture_damage,
+				  &gs->texture_damage, &surface->damage);
+
+	if (!buffer)
+		return;
+
+	texture_used = 0;
+	wl_list_for_each(view, &surface->views, surface_link) {
+		if (view->plane == &surface->compositor->primary_plane) {
+			texture_used = 1;
+			break;
+		}
+	}
+	if (!texture_used)
+		return;
+
+	if (!pixman_region32_not_empty(&gs->texture_damage))
+		goto done;
+
+	if(wl_shm_buffer_get(buffer->resource))
+	{
+		g2d_renderer_copy_shm_buffer(gs, buffer);
+	}
+	else
+	{
+		g2d_renderer_attach_egl(surface, buffer);
+	}
+
+done:
+	pixman_region32_fini(&gs->texture_damage);
+	pixman_region32_init(&gs->texture_damage);
+
+	weston_buffer_reference(&gs->buffer_ref, NULL);
+}
+
+static void
+g2d_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
+			struct wl_shm_buffer *shm_buffer)
+{
+	struct g2d_surface_state *gs = get_surface_state(es);
+	int buffer_length = 0;
+	int alloc_new_buff = 1;
+	int alignedWidth = 0;
+	int height = 0;
+	enum g2d_format g2dFormat = 0;
+	buffer->shm_buffer = shm_buffer;
+	buffer->width = wl_shm_buffer_get_width(shm_buffer);
+	buffer->height = wl_shm_buffer_get_height(shm_buffer);
+	alignedWidth = ALIGN_TO_16(buffer->width);
+
+	switch (wl_shm_buffer_get_format(shm_buffer)) {
+	case WL_SHM_FORMAT_XRGB8888:
+		g2dFormat = G2D_BGRX8888;
+		gs->bpp = 4;
+		break;
+	case WL_SHM_FORMAT_ARGB8888:
+		g2dFormat = G2D_BGRA8888;
+		gs->bpp = 4;
+		break;
+	case WL_SHM_FORMAT_RGB565:
+		g2dFormat = G2D_RGB565;
+		gs->bpp = 2;
+		break;
+	case WL_SHM_FORMAT_YUYV:
+		g2dFormat = G2D_YUYV;
+		height = ALIGN_TO_16(buffer->height);
+		buffer_length = alignedWidth * height * 2;
+		gs->bpp = 2;
+		break;
+	case WL_SHM_FORMAT_YUV420:
+		g2dFormat = G2D_I420;
+		height = ALIGN_TO_16(buffer->height);
+		buffer_length = alignedWidth * height * 3/2;
+		gs->bpp = 1;
+		break;
+	case WL_SHM_FORMAT_NV12:
+		g2dFormat = G2D_NV12;
+		height = ALIGN_TO_16(buffer->height);
+		buffer_length = alignedWidth * height * 3/2;
+		gs->bpp = 1;
+		break;
+	default:
+		weston_log("warning: unknown shm buffer format: %08x\n",
+			   wl_shm_buffer_get_format(shm_buffer));
+		return;
+	}
+
+	if (height == 0)
+		height = buffer->height;
+
+	if (buffer_length == 0)
+		buffer_length = alignedWidth * buffer->height * gs->bpp;
+
+	/* Only allocate a new g2d buff if it is larger than existing one.*/
+	gs->shm_buf_length = buffer_length;
+	if(gs->shm_buf && gs->shm_buf->buf_size > buffer_length)
+	{
+		alloc_new_buff = 0;
+	}
+
+	if(alloc_new_buff)
+	{
+		if(gs->shm_buf)
+			g2d_free(gs->shm_buf);
+		gs->shm_buf = g2d_alloc(buffer_length, 0);
+		gs->g2d_surface.base.planes[0] = gs->shm_buf->buf_paddr;
+		gs->g2d_surface.base.planes[1] = gs->g2d_surface.base.planes[0] + alignedWidth * height;
+		gs->g2d_surface.base.planes[2] = gs->g2d_surface.base.planes[1] + alignedWidth * height / 4;
+	}
+
+	gs->g2d_surface.base.left = 0;
+	gs->g2d_surface.base.top  = 0;
+	gs->g2d_surface.base.right	= buffer->width;
+	gs->g2d_surface.base.bottom = buffer->height;
+	gs->g2d_surface.base.stride = alignedWidth;
+	gs->g2d_surface.base.width	= buffer->width;
+	gs->g2d_surface.base.height = height;
+	gs->g2d_surface.base.rot	= G2D_ROTATION_0;
+	gs->g2d_surface.base.clrcolor = 0xFF400000;
+	gs->g2d_surface.tiling = G2D_LINEAR;
+	gs->g2d_surface.base.format = g2dFormat;
+}
+
+
+static void
+g2d_renderer_get_g2dformat_from_dmabuf(uint32_t dmaformat,
+			enum g2d_format *g2dFormat)
+{
+	switch (dmaformat) {
+		case DRM_FORMAT_ARGB8888:
+			*g2dFormat = G2D_BGRA8888;
+			break;
+		case DRM_FORMAT_XRGB8888:
+			*g2dFormat = G2D_BGRX8888;
+			break;
+		case DRM_FORMAT_RGB565:
+			*g2dFormat = G2D_RGB565;
+			break;
+		case DRM_FORMAT_YUYV:
+			*g2dFormat = G2D_YUYV;
+			break;
+		case DRM_FORMAT_NV12:
+			*g2dFormat = G2D_NV12;
+			break;
+		case DRM_FORMAT_YUV420:
+			*g2dFormat = G2D_I420;
+			break;
+		default:
+			*g2dFormat = -1;
+			weston_log("warning: unknown dmabuf buffer format: %08x\n", dmaformat);
+			break;
+	}
+}
+
+static void
+g2d_renderer_attach_dmabuf(struct weston_surface *es, struct  weston_buffer *buffer,
+			struct linux_dmabuf_buffer *dmabuf)
+{
+	struct g2d_surface_state *gs = get_surface_state(es);
+	int alignedWidth = 0, alignedHeight = 0;
+	enum g2d_format g2dFormat;
+	gctUINT32 paddr = 0;
+	buffer->width = dmabuf->attributes.width;
+	buffer->height = dmabuf->attributes.height;
+	alignedWidth = ALIGN_TO_16(buffer->width);
+	alignedHeight = ALIGN_TO_16(buffer->height);
+
+	g2d_renderer_get_g2dformat_from_dmabuf(dmabuf->attributes.format, &g2dFormat);
+
+	if (g2dFormat < 0)
+		return;
+
+	if(gs->dma_buf)
+		g2d_free(gs->dma_buf);
+	gs->dma_buf = g2d_buf_from_fd(dmabuf->attributes.fd[0]);
+
+	paddr = gs->dma_buf->buf_paddr;
+	switch(g2dFormat){
+		case G2D_I420:
+			gs->g2d_surface.base.planes[0] = paddr;
+			gs->g2d_surface.base.planes[1] = paddr + dmabuf->attributes.offset[1];
+			gs->g2d_surface.base.planes[2] = paddr + dmabuf->attributes.offset[2];
+			break;
+		case G2D_NV12:
+			gs->g2d_surface.base.planes[0] = paddr;
+			gs->g2d_surface.base.planes[1] = paddr + dmabuf->attributes.offset[1];
+			break;
+		case G2D_YUYV:
+		case G2D_RGB565:
+		case G2D_BGRX8888:
+		case G2D_BGRA8888:
+			gs->g2d_surface.base.planes[0] = paddr;
+			break;
+		default:
+			weston_log("G2D render not support format!\n");
+			g2d_free(gs->dma_buf);
+			gs->dma_buf = NULL;
+			return;
+	}
+
+	gs->g2d_surface.base.left = 0;
+	gs->g2d_surface.base.top  = 0;
+	gs->g2d_surface.base.right	= buffer->width;
+	gs->g2d_surface.base.bottom = buffer->height;
+	gs->g2d_surface.base.stride = alignedWidth;
+	gs->g2d_surface.base.width	= alignedWidth;
+	gs->g2d_surface.base.height = alignedHeight;
+	gs->g2d_surface.base.rot	= G2D_ROTATION_0;
+	gs->g2d_surface.tiling = G2D_LINEAR;
+	gs->g2d_surface.base.format = g2dFormat;
+}
+
+static void
+g2d_renderer_query_dmabuf_formats(struct weston_compositor *wc,
+			int **formats, int *num_formats)
+{
+	int num;
+	static const int dma_formats[] = {
+		DRM_FORMAT_ARGB8888,
+		DRM_FORMAT_XRGB8888,
+		DRM_FORMAT_RGB565,
+		DRM_FORMAT_YUYV,
+		DRM_FORMAT_NV12,
+		DRM_FORMAT_YUV420,
+	};
+
+	num = ARRAY_LENGTH(dma_formats);
+	*formats = calloc(num, sizeof(int));
+	memcpy(*formats, dma_formats, num * sizeof(int));
+
+	*num_formats = num;
+}
+
+static void
+g2d_renderer_query_dmabuf_modifiers(struct weston_compositor *wc, int format,
+			uint64_t **modifiers,
+			int *num_modifiers)
+{
+	*num_modifiers = 1;
+	*modifiers = calloc(*num_modifiers, sizeof(uint64_t));
+	(*modifiers)[0] = DRM_FORMAT_MOD_LINEAR;
+}
+
+static bool
+g2d_renderer_import_dmabuf(struct weston_compositor *wc,
+			struct linux_dmabuf_buffer *dmabuf)
+{
+	struct g2d_buf *g2dBuf = NULL;
+	enum g2d_format g2dFormat;
+
+	if (!dmabuf)
+		return false;
+
+	g2d_renderer_get_g2dformat_from_dmabuf(dmabuf->attributes.format, &g2dFormat);
+	if (g2dFormat < 0)
+		return false;
+
+	g2dBuf = g2d_buf_from_fd(dmabuf->attributes.fd[0]);
+
+	if(!g2dBuf)
+		return false;
+	else
+		g2d_free(g2dBuf);
+
+	return true;
+}
+
+static void
+g2d_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
+{
+	struct g2d_surface_state *gs = get_surface_state(es);
+	struct wl_shm_buffer *shm_buffer;
+	struct linux_dmabuf_buffer *dmabuf;
+	weston_buffer_reference(&gs->buffer_ref, buffer);
+
+	if(buffer==NULL)
+		return;
+
+	shm_buffer = wl_shm_buffer_get(buffer->resource);
+
+	if(shm_buffer)
+	{
+		g2d_renderer_attach_shm(es, buffer, shm_buffer);
+	}
+	else if ((dmabuf = linux_dmabuf_buffer_get(buffer->resource)))
+	{
+		g2d_renderer_attach_dmabuf(es, buffer, dmabuf);
+	}
+	else
+	{
+		g2d_renderer_attach_egl(es, buffer);
+	}
+	gs->attached = 1;
+}
+
+static void
+surface_state_destroy(struct g2d_surface_state *gs, struct g2d_renderer *gr)
+{
+	wl_list_remove(&gs->surface_destroy_listener.link);
+	wl_list_remove(&gs->renderer_destroy_listener.link);
+	if(gs->surface)
+		gs->surface->renderer_state = NULL;
+	
+	if(gs->shm_buf)
+	{
+		g2d_free(gs->shm_buf);
+		gs->shm_buf = NULL;
+	}
+	if(gs->dma_buf)
+	{
+		g2d_free(gs->dma_buf);
+		gs->dma_buf = NULL;
+	}
+
+	weston_buffer_reference(&gs->buffer_ref, NULL);
+	free(gs);
+}
+
+static void
+surface_state_handle_surface_destroy(struct wl_listener *listener, void *data)
+{
+	struct g2d_surface_state *gs;
+	struct g2d_renderer *gr;
+
+	gs = container_of(listener, struct g2d_surface_state,
+			  surface_destroy_listener);
+
+	gr = get_renderer(gs->surface->compositor);
+	surface_state_destroy(gs, gr);
+}
+
+static void
+surface_state_handle_renderer_destroy(struct wl_listener *listener, void *data)
+{
+	struct g2d_surface_state *gs;
+	struct g2d_renderer *gr;
+
+	gr = data;
+
+	gs = container_of(listener, struct g2d_surface_state,
+			  renderer_destroy_listener);
+
+	surface_state_destroy(gs, gr);
+}
+
+
+static int
+g2d_renderer_create_surface(struct weston_surface *surface)
+{
+	struct g2d_surface_state *gs;
+	struct g2d_renderer *gr = get_renderer(surface->compositor);
+
+	gs = zalloc(sizeof *gs);
+	if (gs == NULL)
+		return -1;
+
+	/* A buffer is never attached to solid color surfaces, yet
+	 * they still go through texcoord computations. Do not divide
+	 * by zero there.
+	 */
+	gs->pitch = 1;
+
+	gs->surface = surface;
+
+	pixman_region32_init(&gs->texture_damage);
+	surface->renderer_state = gs;
+
+	gs->surface_destroy_listener.notify =
+		surface_state_handle_surface_destroy;
+	wl_signal_add(&surface->destroy_signal,
+			  &gs->surface_destroy_listener);
+
+	gs->renderer_destroy_listener.notify =
+		surface_state_handle_renderer_destroy;
+	wl_signal_add(&gr->destroy_signal,
+			  &gs->renderer_destroy_listener);
+
+	if (surface->buffer_ref.buffer) {
+		g2d_renderer_attach(surface, surface->buffer_ref.buffer);
+		g2d_renderer_flush_damage(surface);
+	}
+	
+	return 0;
+}
+
+static void
+g2d_renderer_surface_set_color(struct weston_surface *surface,
+		 float red, float green, float blue, float alpha)
+{
+	struct g2d_surface_state *gs = get_surface_state(surface);
+
+	gs->color[0] = red;
+	gs->color[1] = green;
+	gs->color[2] = blue;
+	gs->color[3] = alpha;
+}
+
+
+static void
+g2d_renderer_output_destroy(struct weston_output *output)
+{
+	struct g2d_output_state *go = get_output_state(output);
+	int i;
+
+	for (i = 0; i < 2; i++)
+	{
+		pixman_region32_fini(&go->buffer_damage[i]);
+	}
+
+	if(go->offscreen_buf)
+	{
+		g2d_free(go->offscreen_buf);
+		go->offscreen_buf = NULL;
+	}
+
+	if(go->fb_info.fb_fd)
+	{
+		close(go->fb_info.fb_fd);
+		go->fb_info.fb_fd = 0;
+	}
+
+	if(go->renderSurf)
+	{
+		free(go->renderSurf);
+		go->renderSurf = NULL;
+	}
+	for (i = 0; i < go->clone_display_num; i++)
+	{
+		if(go->mirror_fb_info[i].fb_fd)
+		{
+			close(go->mirror_fb_info[i].fb_fd);
+			go->mirror_fb_info[i].fb_fd = 0;
+		}
+	}
+	if(go->mirrorSurf)
+	{
+		free(go->mirrorSurf);
+		go->mirrorSurf = NULL;
+	}
+	if(go->mirror_fb_info)
+	{
+		free(go->mirror_fb_info);
+		go->mirror_fb_info = NULL;
+	}
+
+	free(go);
+}
+
+static void
+g2d_renderer_destroy(struct weston_compositor *ec)
+{
+	struct g2d_renderer *gr = get_renderer(ec);
+
+	wl_signal_emit(&gr->destroy_signal, gr);
+	g2d_close(gr->handle);
+#ifdef ENABLE_EGL
+	if(gr->bind_display)
+		gr->bind_display(gr->egl_display, gr->wl_display);
+	eglTerminate(gr->egl_display);
+	if(!gr->use_drm)
+		fbDestroyDisplay(gr->display);
+#endif
+	free(ec->renderer);
+	ec->renderer = NULL;
+
+	/* remove use-g2d-renderer */
+	char *dir, *path;
+	dir = getenv("XDG_RUNTIME_DIR");
+	path = malloc(strlen(dir) + 40);
+	strcpy(path, dir);
+	strcat(path, "/use-g2d-renderer");
+	remove(path);
+	free(path);
+}
+
+static int
+g2d_renderer_create(struct weston_compositor *ec)
+{
+	struct g2d_renderer *gr;
+	char *dir, *path;
+	mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+	gr = calloc(1, sizeof *gr);
+	if (gr == NULL)
+		return -1;
+
+	gr->base.read_pixels = g2d_renderer_read_pixels;
+	gr->base.repaint_output = g2d_renderer_repaint_output;
+	gr->base.flush_damage = g2d_renderer_flush_damage;
+	gr->base.attach = g2d_renderer_attach;
+	gr->base.surface_set_color = g2d_renderer_surface_set_color;
+	gr->base.destroy = g2d_renderer_destroy;
+	gr->base.import_dmabuf = g2d_renderer_import_dmabuf;
+	gr->base.query_dmabuf_formats = g2d_renderer_query_dmabuf_formats;
+	gr->base.query_dmabuf_modifiers = g2d_renderer_query_dmabuf_modifiers;
+#ifdef ENABLE_EGL
+	gr->bind_display =
+		(void *) eglGetProcAddress("eglBindWaylandDisplayWL");
+	gr->unbind_display =
+		(void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
+	if (!get_platform_display)
+	{
+		get_platform_display = (void *) eglGetProcAddress(
+				"eglGetPlatformDisplayEXT");
+	}
+#endif
+	if(g2d_open(&gr->handle))
+	{
+		weston_log("g2d_open fail.\n");
+		return -1;
+	}
+	ec->renderer = &gr->base;
+	ec->capabilities |= WESTON_CAP_VIEW_CLIP_MASK;
+
+	wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_RGB565);
+	wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_YUV420);
+	wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_NV12);
+	wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_YUYV);
+
+	wl_signal_init(&gr->destroy_signal);
+
+	/* create use-g2d-renderer */
+	
+	dir = getenv("XDG_RUNTIME_DIR");
+	path = malloc(strlen(dir) + 40);
+	strcpy(path, dir);
+	strcat(path, "/use-g2d-renderer");
+	close(open(path, O_CREAT | O_RDWR, mode));
+	free(path);
+
+	return 0;
+}
+
+static int
+g2d_drm_display_create(struct weston_compositor *ec, void *native_window)
+{
+	struct g2d_renderer *gr;
+	if(g2d_renderer_create(ec) < 0)
+	{
+		weston_log("g2d_renderer_create faile.\n");
+		return -1;
+	}
+#ifdef ENABLE_EGL
+	gr = get_renderer(ec);
+	gr->wl_display = ec->wl_display;
+	if(get_platform_display)
+		gr->egl_display = get_platform_display(EGL_PLATFORM_GBM_KHR,
+				native_window, NULL);
+	if(gr->bind_display)
+		gr->bind_display(gr->egl_display, gr->wl_display);
+	gr->use_drm = 1;
+#endif
+	return 0;
+}
+
+static void
+g2d_renderer_output_set_buffer(struct weston_output *output, struct g2d_surfaceEx *buffer)
+{
+	struct g2d_output_state *go = get_output_state(output);
+	go->drm_hw_buffer = buffer;
+}
+
+static int
+g2d_drm_renderer_output_create(struct weston_output *output)
+{
+	struct g2d_output_state *go;
+	int i = 0;
+
+	go = zalloc(sizeof *go);
+	if (go == NULL)
+		return -1;
+	output->renderer_state = go;
+
+	for (i = 0; i < BUFFER_DAMAGE_COUNT; i++)
+		pixman_region32_init(&go->buffer_damage[i]);
+	return 0;
+ }
+
+static int
+drm_create_g2d_image(struct g2d_surfaceEx* g2dSurface,
+				enum g2d_format g2dFormat,
+				void *vaddr,
+				int w, int h, int stride,
+				int size,
+				int dmafd)
+{
+	struct g2d_buf * buffer = NULL;
+
+	buffer = g2d_buf_from_fd(dmafd);
+	if (!buffer)
+		return -1;
+
+	buffer->buf_vaddr = vaddr;
+	buffer->buf_size  = size;
+	g2dSurface->base.planes[0] = buffer->buf_paddr;
+	g2dSurface->base.left = 0;
+	g2dSurface->base.top  = 0;
+	g2dSurface->base.right	= w;
+	g2dSurface->base.bottom = h;
+	g2dSurface->base.stride = w;
+	g2dSurface->base.width	= w;
+	g2dSurface->base.height = h;
+	g2dSurface->base.format = g2dFormat;
+	g2dSurface->base.rot	= G2D_ROTATION_0;
+	g2dSurface->base.clrcolor = 0xFF400000;
+	g2dSurface->tiling = G2D_LINEAR;
+
+	return 0;
+}
+
+static int
+calculate_g2d_format(struct fb_var_screeninfo *varinfo, enum g2d_format *g2dFormat)
+{
+	/* Get the color format. */
+	switch (varinfo->green.length)
+	{
+		case 6:
+			*g2dFormat= G2D_RGB565;
+			break;
+
+		case 8:
+			if (varinfo->blue.offset == 0)
+			{
+				*g2dFormat = (varinfo->transp.length == 0) ? G2D_BGRX8888 : G2D_BGRA8888;
+			}
+			else
+			{
+				*g2dFormat = (varinfo->transp.length == 0) ? G2D_RGBX8888 : G2D_RGBA8888;
+			}
+			break;
+
+		default:
+			*g2dFormat = -1;
+			break;
+	}
+	return 0;
+}
+
+static int
+get_G2dSurface_from_screeninfo(struct fb_screeninfo *info, struct g2d_surfaceEx* g2dSurface)
+{
+	if(info && g2dSurface)
+	{
+		g2dSurface->base.planes[0] = info->physical;
+		g2dSurface->base.left = 0;
+		g2dSurface->base.top  = 0;
+		g2dSurface->base.right	= info->x_resolution;
+		g2dSurface->base.bottom = info->y_resolution;
+		g2dSurface->base.stride = info->stride;
+		g2dSurface->base.width	= info->x_resolution;
+		g2dSurface->base.height = info->y_resolution;
+		g2dSurface->base.format = info->pixel_format;
+		g2dSurface->base.rot	= G2D_ROTATION_0;
+		g2dSurface->base.clrcolor = 0xFF400000;
+		g2dSurface->tiling = G2D_LINEAR;
+		return 0;
+	}
+	return -1;
+}
+
+static int
+fb_query_screen_info(struct g2d_output_state *output, int fd,
+						struct fb_screeninfo *info)
+{
+	struct g2d_output_state *go = output;
+	struct fb_var_screeninfo *varinfo = &info->varinfo;
+	struct fb_fix_screeninfo *fixinfo = &info->fixinfo;
+
+	/* Probe the device for screen information. */
+	if (ioctl(fd, FBIOGET_VSCREENINFO, varinfo) < 0) {
+		return -1;
+	}
+
+	if(go->nNumBuffers > 1){
+		varinfo->yres_virtual = varinfo->yres * go->nNumBuffers;
+		if (ioctl(fd, FBIOPUT_VSCREENINFO, varinfo) < 0)
+			return -1;
+	}
+
+	if (ioctl(fd, FBIOGET_FSCREENINFO, fixinfo) < 0 ||
+		ioctl(fd, FBIOGET_VSCREENINFO, varinfo) < 0){
+		return -1;
+	}
+	/* Store the pertinent data. */
+	info->x_resolution = varinfo->xres;
+	info->y_resolution = varinfo->yres;
+	info->physical = fixinfo->smem_start;
+	info->buffer_length = fixinfo->smem_len;
+	info->stride = fixinfo->line_length / (varinfo->bits_per_pixel >> 3);
+	info->stride_bytes = fixinfo->line_length;
+	calculate_g2d_format(varinfo, &info->pixel_format);
+
+	if (info->pixel_format < 0) {
+		weston_log("Frame buffer uses an unsupported format.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int
+fb_frame_buffer_open(struct g2d_output_state *output, const char *fb_dev,
+						struct fb_screeninfo *screen_info)
+{
+	/* Open the frame buffer device. */
+	screen_info->fb_fd = open(fb_dev, O_RDWR | O_CLOEXEC);
+	if (screen_info->fb_fd < 0) {
+		weston_log("Failed to open frame buffer device%s \n", fb_dev);
+		return -1;
+	}
+
+	/* Grab the screen info. */
+	if (fb_query_screen_info(output, screen_info->fb_fd, screen_info) < 0) {
+		weston_log("Failed to get frame buffer info \n");
+
+		close(screen_info->fb_fd);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void
+getBufferNumber(struct g2d_output_state *go)
+{
+	char *p = NULL;
+	p = getenv("FB_MULTI_BUFFER");
+	if (p == gcvNULL)
+	{
+		go->nNumBuffers = BUFFER_DAMAGE_COUNT;
+	}
+	else
+	{
+		go->nNumBuffers = atoi(p);
+		if (go->nNumBuffers < 2)
+		{
+			go->nNumBuffers  = 1;
+		}
+		else if(go->nNumBuffers >= BUFFER_DAMAGE_COUNT)
+		{
+			go->nNumBuffers = BUFFER_DAMAGE_COUNT;
+			go->activebuffer = 1;
+		}
+	}
+	weston_log("The number of the Framebuffer: %d\n", go->nNumBuffers);
+}
+
+static int
+g2d_renderer_surface_create(struct g2d_output_state *go,
+		struct g2d_renderer *gr,
+		const char *device)
+{
+	int i = 0;
+	int offset = 0;
+	weston_log("Opend device=%s\n", device);
+	if(fb_frame_buffer_open(go, device, &go->fb_info) < 0)
+	{
+		weston_log("Open frame buffer failed.\n");
+		return -1;
+	}
+	go->renderSurf = zalloc(sizeof(struct g2d_surfaceEx) * go->nNumBuffers);
+	offset = go->fb_info.stride_bytes * go->fb_info.y_resolution;
+	for(i = 0; i < go->nNumBuffers; i++)
+	{
+		get_G2dSurface_from_screeninfo(&go->fb_info, &go->renderSurf[i]);
+		go->renderSurf[i].base.planes[0] = go->fb_info.physical
+											+ (offset * i);
+		g2d_clear(gr->handle, &go->renderSurf[i].base);
+	}
+
+	if(go->nNumBuffers == 1)
+	{
+		go->offscreenSurface = (go->renderSurf[go->activebuffer]);
+		go->offscreen_buf = g2d_alloc(go->fb_info.buffer_length, 0);
+		go->offscreenSurface.base.planes[0] = go->offscreen_buf->buf_paddr;
+		g2d_clear(gr->handle, &go->offscreenSurface.base);
+	}
+	return 0;
+}
+
+static int
+g2d_fbdev_renderer_output_create(struct weston_output *output,
+		struct wl_display *wl_display,
+		const char *device)
+ {
+	struct g2d_renderer *gr = get_renderer(output->compositor);
+	struct g2d_output_state *go;
+	int i;
+	int clone_display_num = 0;
+	int count = 0;
+	int k=0, dispCount = 0;
+	char displays[5][32];
+	weston_log("g2d_renderer_output_create device=%s\n", device);
+	count = strlen(device);
+
+	if(count > 0)
+	{
+		for(i= 0; i < count; i++)
+		{
+			if(device[i] == ',')
+			{
+				displays[dispCount][k] = '\0';
+				dispCount++;
+				k = 0;
+				continue;
+			}
+			else if(device[i] != ' ')
+			{
+				displays[dispCount][k++] = device[i];
+			}
+		}
+		displays[dispCount][k] = '\0';
+		clone_display_num = dispCount++;
+		weston_log("clone_display_num = %d\n", clone_display_num);
+	}
+	else
+	{
+		weston_log("Invalid device name\n");
+		return -1;
+	}
+
+	go = zalloc(sizeof *go);
+	if (go == NULL)
+		return -1;
+	go->clone_display_num  = clone_display_num;
+	output->renderer_state = go;
+
+#ifdef ENABLE_EGL
+	gr->wl_display = wl_display;
+	gr->display = fbGetDisplay(wl_display);
+	gr->egl_display = eglGetDisplay(gr->display);
+	if(gr->bind_display)
+		gr->bind_display(gr->egl_display, wl_display);
+#endif
+	getBufferNumber(go);
+
+	if(g2d_renderer_surface_create(go, gr, displays[0]) < 0)
+	{
+		weston_log("Create Render surface failed.\n");
+		return -1;
+	}
+
+	if(go->clone_display_num)
+	{
+		go->mirrorSurf = zalloc(sizeof(struct g2d_surfaceEx) * clone_display_num);
+		go->mirror_fb_info = zalloc(sizeof(struct fb_screeninfo) * clone_display_num);
+		if(go->mirrorSurf == NULL || go->mirror_fb_info == NULL)
+			return -1;
+
+		for(i = 0; i < clone_display_num; i++)
+		{
+			if(fb_frame_buffer_open(go, displays[i + 1], &go->mirror_fb_info[i]) < 0)
+			{
+				weston_log("Open frame buffer failed.\n");
+				return -1;
+			}
+			get_G2dSurface_from_screeninfo(&go->mirror_fb_info[i], &go->mirrorSurf[i]);
+			go->mirrorSurf[i].base.planes[0] = go->mirror_fb_info[i].physical;
+			g2d_clear(gr->handle, &go->mirrorSurf[i].base);
+		}
+	}
+	g2d_finish(gr->handle);
+	for (i = 0; i < BUFFER_DAMAGE_COUNT; i++)
+		pixman_region32_init(&go->buffer_damage[i]);
+	return 0;
+ }
+
+ WL_EXPORT struct g2d_renderer_interface g2d_renderer_interface = {
+	.create = g2d_renderer_create,
+	.drm_display_create  = g2d_drm_display_create,
+	.drm_output_create   = g2d_drm_renderer_output_create,
+	.fbdev_output_create = g2d_fbdev_renderer_output_create,
+	.create_g2d_image    = drm_create_g2d_image,
+	.output_set_buffer   = g2d_renderer_output_set_buffer,
+	.output_destroy      = g2d_renderer_output_destroy,
+};
diff --git a/libweston/g2d-renderer.h b/libweston/g2d-renderer.h
new file mode 100644
index 0000000..15e39a1
--- /dev/null
+++ b/libweston/g2d-renderer.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015 Freescale Semiconductor, Inc.
+ * Copyright © 2013 Vasily Khoruzhick <anarsoul@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __g2d_renderer_h_
+#define __g2d_renderer_h_
+
+#include "compositor.h"
+#include <g2dExt.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/fb.h>
+#include <linux/input.h>
+#include <assert.h>
+
+#ifdef ENABLE_EGL
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#endif
+
+struct g2d_renderer_interface {
+	int (*create)(struct weston_compositor *ec);
+
+	int (*drm_display_create)(struct weston_compositor *ec, void *native_window);
+
+	int (*drm_output_create)(struct weston_output *output);
+
+	int (*fbdev_output_create)(struct weston_output *output,
+				 struct wl_display *wl_display,
+				 const char *device);
+
+	int (*create_g2d_image)(struct g2d_surfaceEx* g2dSurface,
+				enum g2d_format g2dFormat,
+				void *vaddr,
+				int w, int h, int stride,
+				int size,
+				int dmafd);
+
+	void (*output_set_buffer)(struct weston_output *output,
+				struct g2d_surfaceEx *buffer);
+
+	void (*output_destroy)(struct weston_output *output);
+};
+
+#endif