+++ /dev/null
-From 1995ec08267c8063ca72590e700c8612b04a63b5 Mon Sep 17 00:00:00 2001
-From: Meng Mingming <mingming.meng@nxp.com>
-Date: Mon, 16 Jan 2017 10:15:02 +0800
-Subject: [PATCH 2/5] MGS-2521 [#ccc] Enable g2d-renderer for weston 1.11
-
-Enable g2d-renderer for weston 1.11
-weston-start -- --use-g2d=1(--use-gl=1) $OPTARGS
-
-Upstream Status: Inappropriate [i.MX specific]
-
-Date: Jan 16, 2017
-Signed-off-by: Meng Mingming <mingming.meng@nxp.com>
----
- Makefile.am | 16 +
- src/compositor-fbdev.c | 66 ++-
- src/compositor-fbdev.h | 1 +
- src/g2d-renderer.c | 1317 ++++++++++++++++++++++++++++++++++++++++++++++++
- src/g2d-renderer.h | 47 ++
- src/main.c | 6 +-
- 6 files changed, 1448 insertions(+), 5 deletions(-)
- create mode 100644 src/g2d-renderer.c
- create mode 100644 src/g2d-renderer.h
-
-diff --git a/Makefile.am b/Makefile.am
-index 00b74e5..a044b64 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -248,6 +248,22 @@ gl_renderer_la_SOURCES = \
- shared/helpers.h
- endif
-
-+module_LTLIBRARIES += g2d-renderer.la
-+g2d_renderer_la_LDFLAGS = -module -avoid-version
-+g2d_renderer_la_LIBADD = $(COMPOSITOR_LIBS) $(EGL_LIBS) -lg2d
-+g2d_renderer_la_CFLAGS = \
-+ $(COMPOSITOR_CFLAGS) \
-+ $(EGL_CFLAGS) \
-+ $(GCC_CFLAGS) -DHAVE_G2D
-+g2d_renderer_la_SOURCES = \
-+ src/g2d-renderer.h \
-+ src/g2d-renderer.c \
-+ src/vertex-clipping.c \
-+ src/vertex-clipping.h
-+if ENABLE_EGL
-+g2d_renderer_la_CFLAGS += -DENABLE_EGL
-+endif
-+
- if ENABLE_X11_COMPOSITOR
- module_LTLIBRARIES += x11-backend.la
- x11_backend_la_LDFLAGS = -module -avoid-version
-diff --git a/src/compositor-fbdev.c b/src/compositor-fbdev.c
-index 06f4696..cff9513 100644
---- a/src/compositor-fbdev.c
-+++ b/src/compositor-fbdev.c
-@@ -50,6 +50,7 @@
- #include "libinput-seat.h"
- #include "gl-renderer.h"
- #include "presentation-time-server-protocol.h"
-+#include "g2d-renderer.h"
-
- struct fbdev_backend {
- struct weston_backend base;
-@@ -59,6 +60,7 @@ struct fbdev_backend {
- struct udev *udev;
- struct udev_input input;
- int use_pixman;
-+ int use_g2d;
- uint32_t output_transform;
- struct wl_listener session_listener;
- NativeDisplayType display;
-@@ -100,6 +102,7 @@ struct fbdev_output {
- };
-
- struct gl_renderer_interface *gl_renderer;
-+struct g2d_renderer_interface *g2d_renderer;
-
- static const char default_seat[] = "seat0";
-
-@@ -516,6 +519,14 @@ fbdev_output_create(struct fbdev_backend *backend,
- if (backend->use_pixman) {
- if (pixman_renderer_output_create(&output->base) < 0)
- goto out_hw_surface;
-+ } else if(backend->use_g2d) {
-+ const char *g2d_device = device;
-+
-+ if (g2d_renderer->output_create(&output->base,
-+ backend->compositor->wl_display, g2d_device) < 0) {
-+ weston_log("g2d_renderer_output_create failed.\n");
-+ goto out_hw_surface;
-+ }
- } else {
- setenv("HYBRIS_EGLPLATFORM", "wayland", 1);
- output->window = fbCreateWindow(backend->display, -1, -1, 0, 0);
-@@ -571,6 +582,8 @@ fbdev_output_destroy(struct weston_output *base)
- if (backend->use_pixman) {
- if (base->renderer_state != NULL)
- pixman_renderer_output_destroy(base);
-+ } else if(backend->use_g2d) {
-+ g2d_renderer->output_destroy(base);
- } else {
- gl_renderer->output_destroy(base);
- }
-@@ -782,7 +795,8 @@ fbdev_backend_create(struct weston_compositor *compositor, int *argc, char *argv
- backend->base.restore = fbdev_restore;
-
- backend->prev_state = WESTON_COMPOSITOR_ACTIVE;
-- backend->use_pixman = !param->use_gl;
-+ backend->use_pixman = !(param->use_gl || param->use_g2d);
-+ backend->use_g2d = param->use_g2d;
- backend->output_transform = param->output_transform;
-
- weston_setup_vt_switch_bindings(compositor);
-@@ -790,6 +804,46 @@ fbdev_backend_create(struct weston_compositor *compositor, int *argc, char *argv
- if (backend->use_pixman) {
- if (pixman_renderer_init(compositor) < 0)
- goto out_launcher;
-+ } else if(backend->use_g2d) {
-+ int x = 0, y = 0;
-+ int i=0;
-+ int count = 0;
-+ int k=0, dispCount = 0;
-+ char displays[5][32];
-+ 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;
-+ }
-+
-+ weston_log("param->device=%s\n",param->device);
-+ count = strlen(param->device);
-+
-+ for(i= 0; i < count; i++) {
-+ if(param->device[i] == ',') {
-+ displays[dispCount][k] = '\0';
-+ dispCount++;
-+ k = 0;
-+ continue;
-+ }
-+ displays[dispCount][k++] = param->device[i];
-+ }
-+ displays[dispCount][k] = '\0';
-+ dispCount++;
-+
-+ for(i= 0; i < dispCount; i++){
-+ if (fbdev_output_create(backend, x, y, displays[i]) < 0)
-+ goto out_launcher;
-+ x += container_of(backend->compositor->output_list.prev,
-+ struct weston_output,
-+ link)->width;
-+ }
- } else {
- gl_renderer = weston_load_module("gl-renderer.so",
- "gl_renderer_interface");
-@@ -811,7 +865,8 @@ fbdev_backend_create(struct weston_compositor *compositor, int *argc, char *argv
- goto out_launcher;
- }
- }
-- if (fbdev_output_create(backend, 0, 0, param->device) < 0)
-+ if(!backend->use_g2d)
-+ if (fbdev_output_create(backend, 0, 0, param->device) < 0)
- goto out_launcher;
-
- udev_input_init(&backend->input, compositor, backend->udev, seat_id);
-@@ -840,6 +895,7 @@ config_init_to_defaults(struct weston_fbdev_backend_config *config)
- config->tty = 0; /* default to current tty */
- config->device = "/dev/fb0"; /* default frame buffer */
- config->use_gl = 0;
-+ config->use_g2d = 0;
- config->output_transform = WL_OUTPUT_TRANSFORM_NORMAL;
- }
-
-@@ -861,7 +917,11 @@ backend_init(struct weston_compositor *compositor, int *argc, char *argv[],
- config_init_to_defaults(&config);
- memcpy(&config, config_base, config_base->struct_size);
-
-- config.use_gl = 1;
-+ if(config.use_g2d) {
-+ config.use_gl = 0;
-+ } else {
-+ config.use_gl = 1;
-+ }
-
- b = fbdev_backend_create(compositor, argc, argv, wc, &config);
- if (b == NULL)
-diff --git a/src/compositor-fbdev.h b/src/compositor-fbdev.h
-index bd60bdc..32a8598 100644
---- a/src/compositor-fbdev.h
-+++ b/src/compositor-fbdev.h
-@@ -40,6 +40,7 @@ struct weston_fbdev_backend_config {
- int tty;
- char *device;
- int use_gl;
-+ int use_g2d;
-
- uint32_t output_transform;
- };
-diff --git a/src/g2d-renderer.c b/src/g2d-renderer.c
-new file mode 100644
-index 0000000..c30aa62
---- /dev/null
-+++ b/src/g2d-renderer.c
-@@ -0,0 +1,1317 @@
-+/*
-+ * Copyright (c) 2016 Freescale Semiconductor, Inc.
-+ * Copyright © 2012 Intel Corporation
-+ * Copyright © 2015 Collabora, Ltd.
-+ *
-+ * 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 <assert.h>
-+#include <pthread.h>
-+#include <linux/fb.h>
-+#include <sys/ioctl.h>
-+#include <fcntl.h>
-+#include <unistd.h>
-+#include <g2dExt.h>
-+#include <HAL/gc_hal_eglplatform.h>
-+
-+#include "compositor.h"
-+#include "g2d-renderer.h"
-+#include "vertex-clipping.h"
-+#include "shared/helpers.h"
-+
-+#define BUFFER_DAMAGE_COUNT 2
-+#define ALIGN_WIDTH(a) (((a) + 15) & ~15)
-+
-+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;
-+ 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;
-+ 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;
-+#endif
-+ void *handle;
-+};
-+
-+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 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;
-+ }
-+}
-+
-+static int
-+g2d_blitSurface(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(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);
-+ if(!go->directBlit && go->nNumBuffers == 1)
-+ {
-+ g2dRECT srcRect = {0, 0, go->offscreenSurface.base.width, go->offscreenSurface.base.height};
-+ g2dRECT dstrect = srcRect;
-+ g2dRECT clipRect = srcRect;
-+ g2d_set_clipping(gr->handle, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
-+ g2d_blitSurface(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};
-+ g2dRECT clipRect = srcRect;
-+ g2d_set_clipping(gr->handle, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
-+ if(go->directBlit || go->nNumBuffers > 1)
-+ {
-+ g2d_blitSurface(gr->handle, &go->renderSurf[go->activebuffer],
-+ &go->mirrorSurf[i], &srcRect, &dstrect);
-+ }
-+ else
-+ {
-+ g2d_blitSurface(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 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;
-+
-+ 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);
-+ srcRect.left = ev->geometry.x < 0.0 ? g2d_int_from_double(fabsf(ev->geometry.x)) : 0;
-+ srcRect.top = ev->geometry.y < 0.0 ? g2d_int_from_double(fabsf(ev->geometry.y)) : 0;
-+ srcRect.right = ev->surface->width;
-+ srcRect.bottom = ev->surface->height;
-+ if(go->nNumBuffers > 1 || go->directBlit)
-+ {
-+ dstsurface = &go->renderSurf[go->activebuffer];
-+ }
-+ else
-+ {
-+ dstsurface = &go->offscreenSurface;
-+ }
-+ dstWidth = dstsurface->base.width;
-+ dstHeight = dstsurface->base.height;
-+ for (i = 0; i < nrects; i++)
-+ {
-+ pixman_box32_t *rect = &rects[i];
-+ gctFLOAT min_x, max_x, min_y, max_y;
-+
-+ dstrect.left = (bb_rects[0].x1 < 0) ? rect->x1 : bb_rects[0].x1;
-+ dstrect.top = (bb_rects[0].y1 < 0) ? rect->y1 : 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;
-+ }
-+ if(dstrect.left < 0)
-+ {
-+ srcRect.left -= dstrect.left;
-+ dstrect.left = 0;
-+ if(srcRect.left > ev->surface->width)
-+ break;
-+ }
-+ if(dstrect.right > dstWidth)
-+ {
-+ dstrect.right = dstWidth;
-+ srcRect.right = srcRect.left + dstrect.right - dstrect.left;
-+ if(srcRect.right > ev->surface->width)
-+ break;
-+ }
-+ if(dstrect.bottom > dstHeight)
-+ {
-+ dstrect.bottom = dstHeight;
-+ srcRect.bottom = srcRect.top + dstrect.bottom - dstrect.top;
-+ if(srcRect.bottom < 0)
-+ break;
-+ }
-+
-+ 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;
-+ }
-+ g2d_set_clipping(gr->handle, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
-+ g2d_blitSurface(gr->handle, &gs->g2d_surface, 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);
-+ /* repaint bounding region in global coordinates: */
-+ pixman_region32_t repaint;
-+ /* non-opaque region in surface coordinates: */
-+ pixman_region32_t surface_blend;
-+ pixman_region32_t *buffer_damage;
-+
-+ 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;
-+
-+ buffer_damage = &go->buffer_damage[go->current_buffer];
-+ pixman_region32_subtract(buffer_damage, buffer_damage, &repaint);
-+
-+ /* blended region is whole surface minus opaque region: */
-+ pixman_region32_init_rect(&surface_blend, 0, 0,
-+ ev->surface->width, ev->surface->height);
-+ pixman_region32_subtract(&surface_blend, &surface_blend, &ev->surface->opaque);
-+
-+ struct g2d_renderer *gr = get_renderer(ec);
-+ if (pixman_region32_not_empty(&ev->surface->opaque)) {
-+ repaint_region(ev, output, go, &repaint, &ev->surface->opaque);
-+ }
-+
-+ 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);
-+
-+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
-+g2d_renderer_repaint_output(struct weston_output *output,
-+ pixman_region32_t *output_damage)
-+{
-+ struct g2d_output_state *go = get_output_state(output);
-+ struct weston_compositor *compositor = output->compositor;
-+ struct g2d_renderer *gr = get_renderer(compositor);
-+ int i;
-+
-+ use_output(output);
-+ for (i = 0; i < 2; i++)
-+ pixman_region32_union(&go->buffer_damage[i],
-+ &go->buffer_damage[i],
-+ output_damage);
-+
-+ pixman_region32_union(output_damage, output_damage,
-+ &go->buffer_damage[go->current_buffer]);
-+
-+ repaint_views(output, output_damage);
-+ g2d_finish(gr->handle);
-+
-+ pixman_region32_copy(&output->previous_damage, output_damage);
-+ wl_signal_emit(&output->frame_signal, output);
-+ copy_to_framebuffer(output);
-+ go->current_buffer ^= 1;
-+}
-+
-+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_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))
-+ {
-+ uint8_t *src = wl_shm_buffer_get_data(buffer->shm_buffer);
-+ uint8_t *dst = gs->shm_buf->buf_vaddr;
-+ int bpp = gs->bpp;
-+ wl_shm_buffer_begin_access(buffer->shm_buffer);
-+ if(gs->shm_buf)
-+ {
-+ int alignedWidth = ALIGN_WIDTH(buffer->width);
-+ if(alignedWidth == buffer->width)
-+ {
-+ int size = wl_shm_buffer_get_stride(buffer->shm_buffer)*buffer->height;
-+ memcpy(dst, src, size);
-+ }
-+ else
-+ {
-+ int i, j;
-+ for (i = 0; i < buffer->height; i++)
-+ {
-+ for (j = 0; j < buffer->width; j++)
-+ {
-+ int dstOff = i * alignedWidth + j;
-+ int srcOff = (i * buffer->width + j);
-+ memcpy(dst + dstOff * bpp, src + srcOff * bpp, bpp);
-+ }
-+ }
-+ }
-+ }
-+ else
-+ {
-+ weston_log("Error: This shm buffer was not attached\n");
-+ }
-+ wl_shm_buffer_end_access(buffer->shm_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;
-+ 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_WIDTH(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;
-+ default:
-+ weston_log("warning: unknown shm buffer format: %08x\n",
-+ wl_shm_buffer_get_format(shm_buffer));
-+ return;
-+ }
-+
-+ 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.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 = buffer->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_attach(struct weston_surface *es, struct weston_buffer *buffer)
-+{
-+ struct g2d_surface_state *gs = get_surface_state(es);
-+ struct wl_shm_buffer *shm_buffer;
-+ 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
-+ {
-+ 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;
-+ }
-+
-+ 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
-+ eglUnbindWaylandDisplayWL(gr->egl_display);
-+ eglTerminate(gr->egl_display);
-+ fbDestroyDisplay(gr->display);
-+#endif
-+ free(ec->renderer);
-+ ec->renderer = NULL;
-+}
-+
-+static int
-+g2d_renderer_create(struct weston_compositor *ec)
-+{
-+ struct g2d_renderer *gr;
-+ gr = malloc(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;
-+
-+ if(g2d_open(&gr->handle))
-+ {
-+ weston_log("g2d_open fail.\n");
-+ return -1;
-+ }
-+ ec->renderer = &gr->base;
-+ wl_signal_init(&gr->destroy_signal);
-+ 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 = 1;
-+ }
-+ else
-+ {
-+ go->nNumBuffers = atoi(p);
-+ if (go->nNumBuffers < 2)
-+ {
-+ go->nNumBuffers = 1;
-+ }
-+ else if(go->nNumBuffers >= 2)
-+ {
-+ go->nNumBuffers = 2;
-+ go->activebuffer = 1;
-+ }
-+ }
-+ weston_log("FB_MULTI_BUFFER = %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_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);
-+ eglBindWaylandDisplayWL(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,
-+ .output_create = g2d_renderer_output_create,
-+ .output_destroy = g2d_renderer_output_destroy,
-+};
-diff --git a/src/g2d-renderer.h b/src/g2d-renderer.h
-new file mode 100644
-index 0000000..fc4ca49
---- /dev/null
-+++ b/src/g2d-renderer.h
-@@ -0,0 +1,47 @@
-+/*
-+ * 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"
-+
-+#ifdef ENABLE_EGL
-+#include <EGL/egl.h>
-+#include <EGL/eglext.h>
-+#endif
-+
-+struct g2d_renderer_interface {
-+
-+ int (*create)(struct weston_compositor *ec);
-+
-+ int (*output_create)(struct weston_output *output,
-+ struct wl_display *wl_display,
-+ const char *device);
-+
-+ void (*output_destroy)(struct weston_output *output);
-+};
-+
-+#endif
-diff --git a/src/main.c b/src/main.c
-index 3279ac6..5d0bdc4 100644
---- a/src/main.c
-+++ b/src/main.c
-@@ -285,7 +285,8 @@ usage(int error_code)
- "Options for fbdev-backend.so:\n\n"
- " --tty=TTY\t\tThe tty to use\n"
- " --device=DEVICE\tThe framebuffer device to use\n"
-- " --use-gl\t\tUse the GL renderer\n\n");
-+ " --use-gl=1\t\tUse the GL renderer\n"
-+ " --use-g2d=1\t\tUse the g2d renderer\n\n");
- #endif
-
- #if defined(BUILD_HEADLESS_COMPOSITOR)
-@@ -868,7 +869,8 @@ load_fbdev_backend(struct weston_compositor *c, char const * backend,
- const struct weston_option fbdev_options[] = {
- { WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
- { WESTON_OPTION_STRING, "device", 0, &config.device },
-- { WESTON_OPTION_BOOLEAN, "use-gl", 0, &config.use_gl },
-+ { WESTON_OPTION_INTEGER, "use-gl", 0, &config.use_gl },
-+ { WESTON_OPTION_INTEGER, "use-g2d", 0, &config.use_g2d },
- };
-
- parse_options(fbdev_options, ARRAY_LENGTH(fbdev_options), argc, argv);
---
-2.7.4
-