summaryrefslogtreecommitdiffstats
path: root/recipes-graphics/wayland/weston/0002-MGS-2521-ccc-Enable-g2d-renderer-for-weston-1.11.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-graphics/wayland/weston/0002-MGS-2521-ccc-Enable-g2d-renderer-for-weston-1.11.patch')
-rw-r--r--recipes-graphics/wayland/weston/0002-MGS-2521-ccc-Enable-g2d-renderer-for-weston-1.11.patch1605
1 files changed, 1605 insertions, 0 deletions
diff --git a/recipes-graphics/wayland/weston/0002-MGS-2521-ccc-Enable-g2d-renderer-for-weston-1.11.patch b/recipes-graphics/wayland/weston/0002-MGS-2521-ccc-Enable-g2d-renderer-for-weston-1.11.patch
new file mode 100644
index 00000000..858cb81f
--- /dev/null
+++ b/recipes-graphics/wayland/weston/0002-MGS-2521-ccc-Enable-g2d-renderer-for-weston-1.11.patch
@@ -0,0 +1,1605 @@
1From 1995ec08267c8063ca72590e700c8612b04a63b5 Mon Sep 17 00:00:00 2001
2From: Meng Mingming <mingming.meng@nxp.com>
3Date: Mon, 16 Jan 2017 10:15:02 +0800
4Subject: [PATCH 2/5] MGS-2521 [#ccc] Enable g2d-renderer for weston 1.11
5
6Enable g2d-renderer for weston 1.11
7weston-start -- --use-g2d=1(--use-gl=1) $OPTARGS
8
9Upstream Status: Inappropriate [i.MX specific]
10
11Date: Jan 16, 2017
12Signed-off-by: Meng Mingming <mingming.meng@nxp.com>
13---
14 Makefile.am | 16 +
15 src/compositor-fbdev.c | 66 ++-
16 src/compositor-fbdev.h | 1 +
17 src/g2d-renderer.c | 1317 ++++++++++++++++++++++++++++++++++++++++++++++++
18 src/g2d-renderer.h | 47 ++
19 src/main.c | 6 +-
20 6 files changed, 1448 insertions(+), 5 deletions(-)
21 create mode 100644 src/g2d-renderer.c
22 create mode 100644 src/g2d-renderer.h
23
24diff --git a/Makefile.am b/Makefile.am
25index 00b74e5..a044b64 100644
26--- a/Makefile.am
27+++ b/Makefile.am
28@@ -248,6 +248,22 @@ gl_renderer_la_SOURCES = \
29 shared/helpers.h
30 endif
31
32+module_LTLIBRARIES += g2d-renderer.la
33+g2d_renderer_la_LDFLAGS = -module -avoid-version
34+g2d_renderer_la_LIBADD = $(COMPOSITOR_LIBS) $(EGL_LIBS) -lg2d
35+g2d_renderer_la_CFLAGS = \
36+ $(COMPOSITOR_CFLAGS) \
37+ $(EGL_CFLAGS) \
38+ $(GCC_CFLAGS) -DHAVE_G2D
39+g2d_renderer_la_SOURCES = \
40+ src/g2d-renderer.h \
41+ src/g2d-renderer.c \
42+ src/vertex-clipping.c \
43+ src/vertex-clipping.h
44+if ENABLE_EGL
45+g2d_renderer_la_CFLAGS += -DENABLE_EGL
46+endif
47+
48 if ENABLE_X11_COMPOSITOR
49 module_LTLIBRARIES += x11-backend.la
50 x11_backend_la_LDFLAGS = -module -avoid-version
51diff --git a/src/compositor-fbdev.c b/src/compositor-fbdev.c
52index 06f4696..cff9513 100644
53--- a/src/compositor-fbdev.c
54+++ b/src/compositor-fbdev.c
55@@ -50,6 +50,7 @@
56 #include "libinput-seat.h"
57 #include "gl-renderer.h"
58 #include "presentation-time-server-protocol.h"
59+#include "g2d-renderer.h"
60
61 struct fbdev_backend {
62 struct weston_backend base;
63@@ -59,6 +60,7 @@ struct fbdev_backend {
64 struct udev *udev;
65 struct udev_input input;
66 int use_pixman;
67+ int use_g2d;
68 uint32_t output_transform;
69 struct wl_listener session_listener;
70 NativeDisplayType display;
71@@ -100,6 +102,7 @@ struct fbdev_output {
72 };
73
74 struct gl_renderer_interface *gl_renderer;
75+struct g2d_renderer_interface *g2d_renderer;
76
77 static const char default_seat[] = "seat0";
78
79@@ -516,6 +519,14 @@ fbdev_output_create(struct fbdev_backend *backend,
80 if (backend->use_pixman) {
81 if (pixman_renderer_output_create(&output->base) < 0)
82 goto out_hw_surface;
83+ } else if(backend->use_g2d) {
84+ const char *g2d_device = device;
85+
86+ if (g2d_renderer->output_create(&output->base,
87+ backend->compositor->wl_display, g2d_device) < 0) {
88+ weston_log("g2d_renderer_output_create failed.\n");
89+ goto out_hw_surface;
90+ }
91 } else {
92 setenv("HYBRIS_EGLPLATFORM", "wayland", 1);
93 output->window = fbCreateWindow(backend->display, -1, -1, 0, 0);
94@@ -571,6 +582,8 @@ fbdev_output_destroy(struct weston_output *base)
95 if (backend->use_pixman) {
96 if (base->renderer_state != NULL)
97 pixman_renderer_output_destroy(base);
98+ } else if(backend->use_g2d) {
99+ g2d_renderer->output_destroy(base);
100 } else {
101 gl_renderer->output_destroy(base);
102 }
103@@ -782,7 +795,8 @@ fbdev_backend_create(struct weston_compositor *compositor, int *argc, char *argv
104 backend->base.restore = fbdev_restore;
105
106 backend->prev_state = WESTON_COMPOSITOR_ACTIVE;
107- backend->use_pixman = !param->use_gl;
108+ backend->use_pixman = !(param->use_gl || param->use_g2d);
109+ backend->use_g2d = param->use_g2d;
110 backend->output_transform = param->output_transform;
111
112 weston_setup_vt_switch_bindings(compositor);
113@@ -790,6 +804,46 @@ fbdev_backend_create(struct weston_compositor *compositor, int *argc, char *argv
114 if (backend->use_pixman) {
115 if (pixman_renderer_init(compositor) < 0)
116 goto out_launcher;
117+ } else if(backend->use_g2d) {
118+ int x = 0, y = 0;
119+ int i=0;
120+ int count = 0;
121+ int k=0, dispCount = 0;
122+ char displays[5][32];
123+ g2d_renderer = weston_load_module("g2d-renderer.so",
124+ "g2d_renderer_interface");
125+ if (!g2d_renderer) {
126+ weston_log("could not load g2d renderer\n");
127+ goto out_launcher;
128+ }
129+
130+ if (g2d_renderer->create(backend->compositor) < 0) {
131+ weston_log("g2d_renderer_create failed.\n");
132+ goto out_launcher;
133+ }
134+
135+ weston_log("param->device=%s\n",param->device);
136+ count = strlen(param->device);
137+
138+ for(i= 0; i < count; i++) {
139+ if(param->device[i] == ',') {
140+ displays[dispCount][k] = '\0';
141+ dispCount++;
142+ k = 0;
143+ continue;
144+ }
145+ displays[dispCount][k++] = param->device[i];
146+ }
147+ displays[dispCount][k] = '\0';
148+ dispCount++;
149+
150+ for(i= 0; i < dispCount; i++){
151+ if (fbdev_output_create(backend, x, y, displays[i]) < 0)
152+ goto out_launcher;
153+ x += container_of(backend->compositor->output_list.prev,
154+ struct weston_output,
155+ link)->width;
156+ }
157 } else {
158 gl_renderer = weston_load_module("gl-renderer.so",
159 "gl_renderer_interface");
160@@ -811,7 +865,8 @@ fbdev_backend_create(struct weston_compositor *compositor, int *argc, char *argv
161 goto out_launcher;
162 }
163 }
164- if (fbdev_output_create(backend, 0, 0, param->device) < 0)
165+ if(!backend->use_g2d)
166+ if (fbdev_output_create(backend, 0, 0, param->device) < 0)
167 goto out_launcher;
168
169 udev_input_init(&backend->input, compositor, backend->udev, seat_id);
170@@ -840,6 +895,7 @@ config_init_to_defaults(struct weston_fbdev_backend_config *config)
171 config->tty = 0; /* default to current tty */
172 config->device = "/dev/fb0"; /* default frame buffer */
173 config->use_gl = 0;
174+ config->use_g2d = 0;
175 config->output_transform = WL_OUTPUT_TRANSFORM_NORMAL;
176 }
177
178@@ -861,7 +917,11 @@ backend_init(struct weston_compositor *compositor, int *argc, char *argv[],
179 config_init_to_defaults(&config);
180 memcpy(&config, config_base, config_base->struct_size);
181
182- config.use_gl = 1;
183+ if(config.use_g2d) {
184+ config.use_gl = 0;
185+ } else {
186+ config.use_gl = 1;
187+ }
188
189 b = fbdev_backend_create(compositor, argc, argv, wc, &config);
190 if (b == NULL)
191diff --git a/src/compositor-fbdev.h b/src/compositor-fbdev.h
192index bd60bdc..32a8598 100644
193--- a/src/compositor-fbdev.h
194+++ b/src/compositor-fbdev.h
195@@ -40,6 +40,7 @@ struct weston_fbdev_backend_config {
196 int tty;
197 char *device;
198 int use_gl;
199+ int use_g2d;
200
201 uint32_t output_transform;
202 };
203diff --git a/src/g2d-renderer.c b/src/g2d-renderer.c
204new file mode 100644
205index 0000000..c30aa62
206--- /dev/null
207+++ b/src/g2d-renderer.c
208@@ -0,0 +1,1317 @@
209+/*
210+ * Copyright (c) 2016 Freescale Semiconductor, Inc.
211+ * Copyright © 2012 Intel Corporation
212+ * Copyright © 2015 Collabora, Ltd.
213+ *
214+ * Permission is hereby granted, free of charge, to any person obtaining
215+ * a copy of this software and associated documentation files (the
216+ * "Software"), to deal in the Software without restriction, including
217+ * without limitation the rights to use, copy, modify, merge, publish,
218+ * distribute, sublicense, and/or sell copies of the Software, and to
219+ * permit persons to whom the Software is furnished to do so, subject to
220+ * the following conditions:
221+ *
222+ * The above copyright notice and this permission notice (including the
223+ * next paragraph) shall be included in all copies or substantial
224+ * portions of the Software.
225+ *
226+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
227+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
228+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
229+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
230+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
231+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
232+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
233+ * SOFTWARE.
234+ */
235+
236+#define _GNU_SOURCE
237+
238+#include <stdlib.h>
239+#include <string.h>
240+#include <ctype.h>
241+#include <float.h>
242+#include <assert.h>
243+#include <pthread.h>
244+#include <linux/fb.h>
245+#include <sys/ioctl.h>
246+#include <fcntl.h>
247+#include <unistd.h>
248+#include <g2dExt.h>
249+#include <HAL/gc_hal_eglplatform.h>
250+
251+#include "compositor.h"
252+#include "g2d-renderer.h"
253+#include "vertex-clipping.h"
254+#include "shared/helpers.h"
255+
256+#define BUFFER_DAMAGE_COUNT 2
257+#define ALIGN_WIDTH(a) (((a) + 15) & ~15)
258+
259+struct wl_viv_buffer
260+{
261+ struct wl_resource *resource;
262+ gcoSURF surface;
263+ gctINT32 width;
264+ gctINT32 height;
265+ gctINT32 format;
266+ gctUINT alignedWidth;
267+ gctUINT alignedHeight;
268+ gctUINT32 physical[3];
269+ gctUINT32 gpuBaseAddr;
270+ gceTILING tiling;
271+};
272+
273+typedef struct _g2dRECT
274+{
275+ int left;
276+ int top;
277+ int right;
278+ int bottom;
279+} g2dRECT;
280+
281+struct fb_screeninfo {
282+ struct fb_var_screeninfo varinfo;
283+ struct fb_fix_screeninfo fixinfo;
284+ unsigned int x_resolution;
285+ unsigned int y_resolution;
286+ size_t buffer_length; /* length of frame buffer memory in bytes */
287+ size_t physical;
288+ size_t stride;
289+ size_t stride_bytes;
290+ enum g2d_format pixel_format; /* frame buffer pixel format */
291+ int fb_fd;
292+};
293+
294+struct g2d_output_state {
295+ int current_buffer;
296+ pixman_region32_t buffer_damage[BUFFER_DAMAGE_COUNT];
297+ struct g2d_surfaceEx *renderSurf;
298+ int nNumBuffers;
299+ int activebuffer;
300+ struct g2d_surfaceEx offscreenSurface;
301+ struct g2d_buf *offscreen_buf;
302+ struct fb_screeninfo fb_info;
303+ struct fb_screeninfo *mirror_fb_info;
304+ struct g2d_surfaceEx *mirrorSurf;
305+ int directBlit;
306+ int clone_display_num;
307+ int width;
308+ int height;
309+};
310+
311+struct g2d_surface_state {
312+ float color[4];
313+ struct weston_buffer_reference buffer_ref;
314+ int pitch; /* in pixels */
315+ int attached;
316+ pixman_region32_t texture_damage;
317+ struct g2d_surfaceEx g2d_surface;
318+ struct g2d_buf *shm_buf;
319+ int shm_buf_length;
320+ int bpp;
321+
322+ struct weston_surface *surface;
323+ struct wl_listener surface_destroy_listener;
324+ struct wl_listener renderer_destroy_listener;
325+};
326+
327+struct g2d_renderer {
328+ struct weston_renderer base;
329+ struct wl_signal destroy_signal;
330+#ifdef ENABLE_EGL
331+ NativeDisplayType display;
332+ EGLDisplay egl_display;
333+ struct wl_display *wl_display;
334+#endif
335+ void *handle;
336+};
337+
338+static int
339+g2d_renderer_create_surface(struct weston_surface *surface);
340+
341+static inline struct g2d_surface_state *
342+get_surface_state(struct weston_surface *surface)
343+{
344+ if (!surface->renderer_state)
345+ g2d_renderer_create_surface(surface);
346+ return (struct g2d_surface_state *)surface->renderer_state;
347+}
348+
349+static inline struct g2d_renderer *
350+get_renderer(struct weston_compositor *ec)
351+{
352+ return (struct g2d_renderer *)ec->renderer;
353+}
354+
355+#define max(a, b) (((a) > (b)) ? (a) : (b))
356+#define min(a, b) (((a) > (b)) ? (b) : (a))
357+/*
358+ * Compute the boundary vertices of the intersection of the global coordinate
359+ * aligned rectangle 'rect', and an arbitrary quadrilateral produced from
360+ * 'surf_rect' when transformed from surface coordinates into global coordinates.
361+ * The vertices are written to 'ex' and 'ey', and the return value is the
362+ * number of vertices. Vertices are produced in clockwise winding order.
363+ * Guarantees to produce either zero vertices, or 3-8 vertices with non-zero
364+ * polygon area.
365+ */
366+static int
367+calculate_edges(struct weston_view *ev, pixman_box32_t *rect,
368+ pixman_box32_t *surf_rect, float *ex, float *ey)
369+{
370+
371+ struct clip_context ctx;
372+ int i, n;
373+ float min_x, max_x, min_y, max_y;
374+ struct polygon8 surf = {
375+ { surf_rect->x1, surf_rect->x2, surf_rect->x2, surf_rect->x1 },
376+ { surf_rect->y1, surf_rect->y1, surf_rect->y2, surf_rect->y2 },
377+ 4
378+ };
379+
380+ ctx.clip.x1 = rect->x1;
381+ ctx.clip.y1 = rect->y1;
382+ ctx.clip.x2 = rect->x2;
383+ ctx.clip.y2 = rect->y2;
384+
385+ /* transform surface to screen space: */
386+ for (i = 0; i < surf.n; i++)
387+ weston_view_to_global_float(ev, surf.x[i], surf.y[i],
388+ &surf.x[i], &surf.y[i]);
389+
390+ /* find bounding box: */
391+ min_x = max_x = surf.x[0];
392+ min_y = max_y = surf.y[0];
393+
394+ for (i = 1; i < surf.n; i++) {
395+ min_x = min(min_x, surf.x[i]);
396+ max_x = max(max_x, surf.x[i]);
397+ min_y = min(min_y, surf.y[i]);
398+ max_y = max(max_y, surf.y[i]);
399+ }
400+
401+ /* First, simple bounding box check to discard early transformed
402+ * surface rects that do not intersect with the clip region:
403+ */
404+ if ((min_x >= ctx.clip.x2) || (max_x <= ctx.clip.x1) ||
405+ (min_y >= ctx.clip.y2) || (max_y <= ctx.clip.y1))
406+ return 0;
407+
408+ /* Simple case, bounding box edges are parallel to surface edges,
409+ * there will be only four edges. We just need to clip the surface
410+ * vertices to the clip rect bounds:
411+ */
412+ if (!ev->transform.enabled)
413+ return clip_simple(&ctx, &surf, ex, ey);
414+
415+ /* Transformed case: use a general polygon clipping algorithm to
416+ * clip the surface rectangle with each side of 'rect'.
417+ * The algorithm is Sutherland-Hodgman, as explained in
418+ * http://www.codeguru.com/cpp/misc/misc/graphics/article.php/c8965/Polygon-Clipping.htm
419+ * but without looking at any of that code.
420+ */
421+ n = clip_transformed(&ctx, &surf, ex, ey);
422+
423+ if (n < 3)
424+ return 0;
425+
426+ return n;
427+}
428+
429+
430+static inline struct g2d_output_state *
431+get_output_state(struct weston_output *output)
432+{
433+ return (struct g2d_output_state *)output->renderer_state;
434+}
435+
436+static void
437+g2d_getG2dTiling(IN gceTILING tiling, enum g2d_tiling* g2dTiling)
438+{
439+ switch(tiling)
440+ {
441+ case gcvLINEAR:
442+ *g2dTiling = G2D_LINEAR;
443+ break;
444+ case gcvTILED:
445+ *g2dTiling = G2D_TILED;
446+ break;
447+ case gcvSUPERTILED:
448+ *g2dTiling = G2D_SUPERTILED;
449+ break;
450+ default:
451+ weston_log("Error in function %s\n", __func__);
452+ break;
453+ }
454+}
455+
456+static void
457+g2d_getG2dFormat(IN gceSURF_FORMAT Format, enum g2d_format* g2dFormat)
458+{
459+ switch(Format)
460+ {
461+ case gcvSURF_R5G6B5:
462+ *g2dFormat = G2D_RGB565;
463+ break;
464+ case gcvSURF_A8B8G8R8:
465+ *g2dFormat = G2D_RGBA8888;
466+ break;
467+ case gcvSURF_X8B8G8R8:
468+ *g2dFormat = G2D_RGBA8888;
469+ break;
470+ case gcvSURF_A8R8G8B8:
471+ *g2dFormat = G2D_BGRA8888;
472+ break;
473+ case gcvSURF_X8R8G8B8:
474+ *g2dFormat = G2D_BGRX8888;
475+ break;
476+ case gcvSURF_B5G6R5:
477+ *g2dFormat = G2D_BGR565;
478+ break;
479+ case gcvSURF_B8G8R8A8:
480+ *g2dFormat = G2D_ARGB8888;
481+ break;
482+ case gcvSURF_R8G8B8A8:
483+ *g2dFormat = G2D_ABGR8888;
484+ break;
485+ case gcvSURF_B8G8R8X8:
486+ *g2dFormat = G2D_XRGB8888;
487+ break;
488+ case gcvSURF_R8G8B8X8:
489+ *g2dFormat = G2D_XBGR8888;
490+ break;
491+ case gcvSURF_NV12:
492+ *g2dFormat = G2D_NV12;
493+ break;
494+ case gcvSURF_NV21:
495+ *g2dFormat = G2D_NV21;
496+ break;
497+ case gcvSURF_I420:
498+ *g2dFormat = G2D_I420;
499+ break;
500+ case gcvSURF_YV12:
501+ *g2dFormat = G2D_YV12;
502+ break;
503+ case gcvSURF_YUY2:
504+ *g2dFormat = G2D_YUYV;
505+ break;
506+ case gcvSURF_YVYU:
507+ *g2dFormat = G2D_YVYU;
508+ break;
509+ case gcvSURF_UYVY:
510+ *g2dFormat = G2D_UYVY;
511+ break;
512+ case gcvSURF_VYUY:
513+ *g2dFormat = G2D_VYUY;
514+ break;
515+ case gcvSURF_NV16:
516+ *g2dFormat = G2D_NV16;
517+ break;
518+ case gcvSURF_NV61:
519+ *g2dFormat = G2D_NV61;
520+ break;
521+ default:
522+ weston_log("Error in function %s, Format not supported\n", __func__);
523+ break;
524+ }
525+}
526+
527+static void printG2dSurfaceInfo(struct g2d_surfaceEx* g2dSurface, const char* msg)
528+{
529+ weston_log("%s physicAddr = %x left = %d right = %d top=%d bottom=%d stride= %d tiling = %d, format=%d \n",
530+ msg,
531+ g2dSurface->base.planes[0],
532+ g2dSurface->base.left,
533+ g2dSurface->base.right,
534+ g2dSurface->base.top,
535+ g2dSurface->base.bottom,
536+ g2dSurface->base.stride,
537+ g2dSurface->tiling,
538+ g2dSurface->base.format);
539+}
540+
541+static void
542+get_g2dSurface(struct wl_viv_buffer *buffer, struct g2d_surfaceEx *g2dSurface)
543+{
544+ if(buffer->width < 0 || buffer->height < 0)
545+ {
546+ weston_log("invalid EGL buffer in function %s\n", __func__);
547+ return;
548+ }
549+ g2d_getG2dFormat(buffer->format, &g2dSurface->base.format);
550+ g2d_getG2dTiling(buffer->tiling, &g2dSurface->tiling);
551+ g2dSurface->base.planes[0] = buffer->physical[0] + buffer->gpuBaseAddr;
552+ g2dSurface->base.planes[1] = buffer->physical[1] + buffer->gpuBaseAddr;
553+ g2dSurface->base.planes[2] = buffer->physical[2] + buffer->gpuBaseAddr;
554+ g2dSurface->base.left = 0;
555+ g2dSurface->base.top = 0;
556+ g2dSurface->base.right = buffer->width;
557+ g2dSurface->base.bottom = buffer->height;
558+ g2dSurface->base.stride = buffer->alignedWidth;
559+ g2dSurface->base.width = buffer->width;
560+ g2dSurface->base.height = buffer->height;
561+ g2dSurface->base.rot = G2D_ROTATION_0;
562+}
563+
564+static void
565+g2d_SetSurfaceRect(struct g2d_surfaceEx* g2dSurface, g2dRECT* rect)
566+{
567+ if(g2dSurface && rect)
568+ {
569+ g2dSurface->base.left = rect->left;
570+ g2dSurface->base.top = rect->top;
571+ g2dSurface->base.right = rect->right;
572+ g2dSurface->base.bottom = rect->bottom;
573+ }
574+}
575+
576+static int
577+g2d_blitSurface(void *handle, struct g2d_surfaceEx * srcG2dSurface, struct g2d_surfaceEx *dstG2dSurface,
578+ g2dRECT *srcRect, g2dRECT *dstRect)
579+{
580+ g2d_SetSurfaceRect(srcG2dSurface, srcRect);
581+ g2d_SetSurfaceRect(dstG2dSurface, dstRect);
582+ srcG2dSurface->base.blendfunc = G2D_ONE;
583+ dstG2dSurface->base.blendfunc = G2D_ONE_MINUS_SRC_ALPHA;
584+
585+ if(g2d_blitEx(handle, srcG2dSurface, dstG2dSurface))
586+ {
587+ printG2dSurfaceInfo(srcG2dSurface, "SRC:");
588+ printG2dSurfaceInfo(dstG2dSurface, "DST:");
589+ return -1;
590+ }
591+ return 0;
592+}
593+
594+static void
595+g2d_flip_surface(struct weston_output *output)
596+{
597+ struct g2d_output_state *go = get_output_state(output);
598+ go->fb_info.varinfo.yoffset = go->activebuffer * go->fb_info.y_resolution;
599+
600+ if(ioctl(go->fb_info.fb_fd, FBIOPAN_DISPLAY, &(go->fb_info.varinfo)) < 0)
601+ {
602+ weston_log("FBIOPAN_DISPLAY Failed\n");
603+ }
604+ go->activebuffer = (go->activebuffer + 1) % go->nNumBuffers;
605+}
606+
607+static void
608+copy_to_framebuffer(struct weston_output *output)
609+{
610+ struct g2d_renderer *gr = get_renderer(output->compositor);
611+ struct g2d_output_state *go = get_output_state(output);
612+ if(!go->directBlit && go->nNumBuffers == 1)
613+ {
614+ g2dRECT srcRect = {0, 0, go->offscreenSurface.base.width, go->offscreenSurface.base.height};
615+ g2dRECT dstrect = srcRect;
616+ g2dRECT clipRect = srcRect;
617+ g2d_set_clipping(gr->handle, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
618+ g2d_blitSurface(gr->handle, &go->offscreenSurface,
619+ &go->renderSurf[go->activebuffer], &srcRect, &dstrect);
620+ }
621+
622+ if(go->clone_display_num)
623+ {
624+ int i = 0;
625+ for(i = 0; i < go->clone_display_num; i++)
626+ {
627+ g2dRECT srcRect = {0, 0, go->renderSurf[go->activebuffer].base.width, go->renderSurf[go->activebuffer].base.height};
628+ g2dRECT dstrect = {0, 0, go->mirrorSurf[i].base.width, go->mirrorSurf[i].base.height};
629+ g2dRECT clipRect = srcRect;
630+ g2d_set_clipping(gr->handle, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
631+ if(go->directBlit || go->nNumBuffers > 1)
632+ {
633+ g2d_blitSurface(gr->handle, &go->renderSurf[go->activebuffer],
634+ &go->mirrorSurf[i], &srcRect, &dstrect);
635+ }
636+ else
637+ {
638+ g2d_blitSurface(gr->handle, &go->offscreenSurface,
639+ &go->mirrorSurf[i], &srcRect, &dstrect);
640+ }
641+ }
642+ }
643+
644+ g2d_finish(gr->handle);
645+
646+ if(go->nNumBuffers > 1)
647+ {
648+ g2d_flip_surface(output);
649+ }
650+}
651+
652+static int
653+is_view_visible(struct weston_view *view)
654+{
655+ /* Return false, if surface is guaranteed to be totally obscured. */
656+ int ret;
657+ pixman_region32_t unocc;
658+
659+ pixman_region32_init(&unocc);
660+ pixman_region32_subtract(&unocc, &view->transform.boundingbox,
661+ &view->clip);
662+ ret = pixman_region32_not_empty(&unocc);
663+ pixman_region32_fini(&unocc);
664+
665+ return ret;
666+}
667+
668+static void
669+use_output(struct weston_output *output)
670+{
671+ struct weston_compositor *compositor = output->compositor;
672+ struct weston_view *view;
673+ struct g2d_output_state *go = get_output_state(output);
674+ int visibleViews=0;
675+ int fullscreenViews=0;
676+
677+ if(go->nNumBuffers == 1)
678+ {
679+ wl_list_for_each_reverse(view, &compositor->view_list, link)
680+ if (view->plane == &compositor->primary_plane && is_view_visible(view))
681+ {
682+ visibleViews++;
683+ if(view->surface->width == go->width && view->surface->height == go->height)
684+ {
685+ pixman_box32_t *bb_rects;
686+ int nbb=0;
687+ bb_rects = pixman_region32_rectangles(&view->transform.boundingbox, &nbb);
688+ if(nbb == 1)
689+ if(bb_rects[0].x1 == 0 && bb_rects[0].y1 ==0)
690+ fullscreenViews++;
691+ }
692+ }
693+
694+ go->directBlit = ((visibleViews == 1) || (fullscreenViews > 1));
695+ }
696+}
697+
698+static int
699+g2d_renderer_read_pixels(struct weston_output *output,
700+ pixman_format_code_t format, void *pixels,
701+ uint32_t x, uint32_t y,
702+ uint32_t width, uint32_t height)
703+{
704+ return 0;
705+}
706+
707+static int g2d_int_from_double(double d)
708+{
709+ return wl_fixed_to_int(wl_fixed_from_double(d));
710+}
711+
712+static void
713+repaint_region(struct weston_view *ev, struct weston_output *output, struct g2d_output_state *go, pixman_region32_t *region,
714+ pixman_region32_t *surf_region){
715+
716+ struct g2d_renderer *gr = get_renderer(ev->surface->compositor);
717+ struct g2d_surface_state *gs = get_surface_state(ev->surface);
718+
719+ pixman_box32_t *rects, *surf_rects, *bb_rects;
720+ int i, j, nrects, nsurf, nbb=0;
721+ g2dRECT srcRect = {0};
722+ g2dRECT dstrect = {0};
723+ g2dRECT clipRect = {0};
724+ int dstWidth = 0;
725+ int dstHeight = 0;
726+ struct g2d_surfaceEx *dstsurface;
727+
728+ bb_rects = pixman_region32_rectangles(&ev->transform.boundingbox, &nbb);
729+
730+ if(!gs->attached || nbb <= 0)
731+ {
732+ return;
733+ }
734+
735+ rects = pixman_region32_rectangles(region, &nrects);
736+ surf_rects = pixman_region32_rectangles(surf_region, &nsurf);
737+ srcRect.left = ev->geometry.x < 0.0 ? g2d_int_from_double(fabsf(ev->geometry.x)) : 0;
738+ srcRect.top = ev->geometry.y < 0.0 ? g2d_int_from_double(fabsf(ev->geometry.y)) : 0;
739+ srcRect.right = ev->surface->width;
740+ srcRect.bottom = ev->surface->height;
741+ if(go->nNumBuffers > 1 || go->directBlit)
742+ {
743+ dstsurface = &go->renderSurf[go->activebuffer];
744+ }
745+ else
746+ {
747+ dstsurface = &go->offscreenSurface;
748+ }
749+ dstWidth = dstsurface->base.width;
750+ dstHeight = dstsurface->base.height;
751+ for (i = 0; i < nrects; i++)
752+ {
753+ pixman_box32_t *rect = &rects[i];
754+ gctFLOAT min_x, max_x, min_y, max_y;
755+
756+ dstrect.left = (bb_rects[0].x1 < 0) ? rect->x1 : bb_rects[0].x1;
757+ dstrect.top = (bb_rects[0].y1 < 0) ? rect->y1 : bb_rects[0].y1;
758+ dstrect.right = bb_rects[0].x2;
759+ dstrect.bottom = bb_rects[0].y2;
760+ /*Multi display support*/
761+ if(output->x > 0)
762+ {
763+ dstrect.left = dstrect.left - output->x;
764+ dstrect.right = dstrect.right - output->x;
765+ }
766+ if(dstrect.left < 0)
767+ {
768+ srcRect.left -= dstrect.left;
769+ dstrect.left = 0;
770+ if(srcRect.left > ev->surface->width)
771+ break;
772+ }
773+ if(dstrect.right > dstWidth)
774+ {
775+ dstrect.right = dstWidth;
776+ srcRect.right = srcRect.left + dstrect.right - dstrect.left;
777+ if(srcRect.right > ev->surface->width)
778+ break;
779+ }
780+ if(dstrect.bottom > dstHeight)
781+ {
782+ dstrect.bottom = dstHeight;
783+ srcRect.bottom = srcRect.top + dstrect.bottom - dstrect.top;
784+ if(srcRect.bottom < 0)
785+ break;
786+ }
787+
788+ for (j = 0; j < nsurf; j++)
789+ {
790+ pixman_box32_t *surf_rect = &surf_rects[j];
791+ gctFLOAT ex[8], ey[8]; /* edge points in screen space */
792+ int n;
793+ int m=0;
794+ n = calculate_edges(ev, rect, surf_rect, ex, ey);
795+ if (n < 3)
796+ continue;
797+
798+ min_x = max_x = ex[0];
799+ min_y = max_y = ey[0];
800+ for (m = 1; m < n; m++)
801+ {
802+ min_x = min(min_x, ex[m]);
803+ max_x = max(max_x, ex[m]);
804+ min_y = min(min_y, ey[m]);
805+ max_y = max(max_y, ey[m]);
806+ }
807+
808+ clipRect.left = g2d_int_from_double(min_x);
809+ clipRect.top = g2d_int_from_double(min_y);
810+ clipRect.right = g2d_int_from_double(max_x);
811+ clipRect.bottom = g2d_int_from_double(max_y);
812+
813+ if(output->x > 0)
814+ {
815+ clipRect.left = clipRect.left - output->x;
816+ clipRect.right = clipRect.right - output->x;
817+ }
818+ g2d_set_clipping(gr->handle, clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
819+ g2d_blitSurface(gr->handle, &gs->g2d_surface, dstsurface, &srcRect, &dstrect);
820+ }
821+ }
822+}
823+
824+static void
825+draw_view(struct weston_view *ev, struct weston_output *output,
826+ pixman_region32_t *damage) /* in global coordinates */
827+{
828+ struct weston_compositor *ec = ev->surface->compositor;
829+ struct g2d_output_state *go = get_output_state(output);
830+ struct g2d_surface_state *gs = get_surface_state(ev->surface);
831+ /* repaint bounding region in global coordinates: */
832+ pixman_region32_t repaint;
833+ /* non-opaque region in surface coordinates: */
834+ pixman_region32_t surface_blend;
835+ pixman_region32_t *buffer_damage;
836+
837+ pixman_region32_init(&repaint);
838+ pixman_region32_intersect(&repaint,
839+ &ev->transform.boundingbox, damage);
840+ pixman_region32_subtract(&repaint, &repaint, &ev->clip);
841+
842+ if (!pixman_region32_not_empty(&repaint))
843+ goto out;
844+
845+ buffer_damage = &go->buffer_damage[go->current_buffer];
846+ pixman_region32_subtract(buffer_damage, buffer_damage, &repaint);
847+
848+ /* blended region is whole surface minus opaque region: */
849+ pixman_region32_init_rect(&surface_blend, 0, 0,
850+ ev->surface->width, ev->surface->height);
851+ pixman_region32_subtract(&surface_blend, &surface_blend, &ev->surface->opaque);
852+
853+ struct g2d_renderer *gr = get_renderer(ec);
854+ if (pixman_region32_not_empty(&ev->surface->opaque)) {
855+ repaint_region(ev, output, go, &repaint, &ev->surface->opaque);
856+ }
857+
858+ if (pixman_region32_not_empty(&surface_blend)) {
859+ g2d_enable(gr->handle,G2D_BLEND);
860+ if (ev->alpha < 1.0)
861+ {
862+ g2d_enable(gr->handle, G2D_GLOBAL_ALPHA);
863+ gs->g2d_surface.base.global_alpha = ev->alpha * 0xFF;
864+ }
865+ repaint_region(ev, output, go, &repaint, &surface_blend);
866+ g2d_disable(gr->handle, G2D_GLOBAL_ALPHA);
867+ g2d_disable(gr->handle, G2D_BLEND);
868+ }
869+ pixman_region32_fini(&surface_blend);
870+
871+out:
872+ pixman_region32_fini(&repaint);
873+}
874+
875+static void
876+repaint_views(struct weston_output *output, pixman_region32_t *damage)
877+{
878+ struct weston_compositor *compositor = output->compositor;
879+ struct weston_view *view;
880+
881+ wl_list_for_each_reverse(view, &compositor->view_list, link)
882+ if (view->plane == &compositor->primary_plane)
883+ draw_view(view, output, damage);
884+}
885+
886+static void
887+g2d_renderer_repaint_output(struct weston_output *output,
888+ pixman_region32_t *output_damage)
889+{
890+ struct g2d_output_state *go = get_output_state(output);
891+ struct weston_compositor *compositor = output->compositor;
892+ struct g2d_renderer *gr = get_renderer(compositor);
893+ int i;
894+
895+ use_output(output);
896+ for (i = 0; i < 2; i++)
897+ pixman_region32_union(&go->buffer_damage[i],
898+ &go->buffer_damage[i],
899+ output_damage);
900+
901+ pixman_region32_union(output_damage, output_damage,
902+ &go->buffer_damage[go->current_buffer]);
903+
904+ repaint_views(output, output_damage);
905+ g2d_finish(gr->handle);
906+
907+ pixman_region32_copy(&output->previous_damage, output_damage);
908+ wl_signal_emit(&output->frame_signal, output);
909+ copy_to_framebuffer(output);
910+ go->current_buffer ^= 1;
911+}
912+
913+static void
914+g2d_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer)
915+{
916+ struct wl_viv_buffer *vivBuffer = wl_resource_get_user_data(buffer->resource);
917+ struct g2d_surface_state *gs = get_surface_state(es);
918+ buffer->width = vivBuffer->width;
919+ buffer->height = vivBuffer->height;
920+ get_g2dSurface(vivBuffer, &gs->g2d_surface);
921+}
922+
923+static void
924+g2d_renderer_flush_damage(struct weston_surface *surface)
925+{
926+ struct g2d_surface_state *gs = get_surface_state(surface);
927+ struct weston_buffer *buffer = gs->buffer_ref.buffer;
928+ struct weston_view *view;
929+ int texture_used;
930+ pixman_region32_union(&gs->texture_damage,
931+ &gs->texture_damage, &surface->damage);
932+
933+ if (!buffer)
934+ return;
935+
936+ texture_used = 0;
937+ wl_list_for_each(view, &surface->views, surface_link) {
938+ if (view->plane == &surface->compositor->primary_plane) {
939+ texture_used = 1;
940+ break;
941+ }
942+ }
943+ if (!texture_used)
944+ return;
945+
946+ if (!pixman_region32_not_empty(&gs->texture_damage))
947+ goto done;
948+
949+ if(wl_shm_buffer_get(buffer->resource))
950+ {
951+ uint8_t *src = wl_shm_buffer_get_data(buffer->shm_buffer);
952+ uint8_t *dst = gs->shm_buf->buf_vaddr;
953+ int bpp = gs->bpp;
954+ wl_shm_buffer_begin_access(buffer->shm_buffer);
955+ if(gs->shm_buf)
956+ {
957+ int alignedWidth = ALIGN_WIDTH(buffer->width);
958+ if(alignedWidth == buffer->width)
959+ {
960+ int size = wl_shm_buffer_get_stride(buffer->shm_buffer)*buffer->height;
961+ memcpy(dst, src, size);
962+ }
963+ else
964+ {
965+ int i, j;
966+ for (i = 0; i < buffer->height; i++)
967+ {
968+ for (j = 0; j < buffer->width; j++)
969+ {
970+ int dstOff = i * alignedWidth + j;
971+ int srcOff = (i * buffer->width + j);
972+ memcpy(dst + dstOff * bpp, src + srcOff * bpp, bpp);
973+ }
974+ }
975+ }
976+ }
977+ else
978+ {
979+ weston_log("Error: This shm buffer was not attached\n");
980+ }
981+ wl_shm_buffer_end_access(buffer->shm_buffer);
982+ }
983+ else
984+ {
985+ g2d_renderer_attach_egl(surface, buffer);
986+ }
987+
988+done:
989+ pixman_region32_fini(&gs->texture_damage);
990+ pixman_region32_init(&gs->texture_damage);
991+
992+ weston_buffer_reference(&gs->buffer_ref, NULL);
993+}
994+
995+static void
996+g2d_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
997+ struct wl_shm_buffer *shm_buffer)
998+{
999+ struct g2d_surface_state *gs = get_surface_state(es);
1000+ int buffer_length = 0;
1001+ int alloc_new_buff = 1;
1002+ int alignedWidth = 0;
1003+ enum g2d_format g2dFormat = 0;
1004+ buffer->shm_buffer = shm_buffer;
1005+ buffer->width = wl_shm_buffer_get_width(shm_buffer);
1006+ buffer->height = wl_shm_buffer_get_height(shm_buffer);
1007+ alignedWidth = ALIGN_WIDTH(buffer->width);
1008+
1009+ switch (wl_shm_buffer_get_format(shm_buffer)) {
1010+ case WL_SHM_FORMAT_XRGB8888:
1011+ g2dFormat = G2D_BGRX8888;
1012+ gs->bpp = 4;
1013+ break;
1014+ case WL_SHM_FORMAT_ARGB8888:
1015+ g2dFormat = G2D_BGRA8888;
1016+ gs->bpp = 4;
1017+ break;
1018+ case WL_SHM_FORMAT_RGB565:
1019+ g2dFormat = G2D_RGB565;
1020+ gs->bpp = 2;
1021+ break;
1022+ default:
1023+ weston_log("warning: unknown shm buffer format: %08x\n",
1024+ wl_shm_buffer_get_format(shm_buffer));
1025+ return;
1026+ }
1027+
1028+ buffer_length = alignedWidth * buffer->height * gs->bpp;
1029+
1030+ /* Only allocate a new g2d buff if it is larger than existing one.*/
1031+ gs->shm_buf_length = buffer_length;
1032+ if(gs->shm_buf && gs->shm_buf->buf_size > buffer_length)
1033+ {
1034+ alloc_new_buff = 0;
1035+ }
1036+
1037+ if(alloc_new_buff)
1038+ {
1039+ if(gs->shm_buf)
1040+ g2d_free(gs->shm_buf);
1041+ gs->shm_buf = g2d_alloc(buffer_length, 0);
1042+ gs->g2d_surface.base.planes[0] = gs->shm_buf->buf_paddr;
1043+ }
1044+ gs->g2d_surface.base.left = 0;
1045+ gs->g2d_surface.base.top = 0;
1046+ gs->g2d_surface.base.right = buffer->width;
1047+ gs->g2d_surface.base.bottom = buffer->height;
1048+ gs->g2d_surface.base.stride = alignedWidth;
1049+ gs->g2d_surface.base.width = buffer->width;
1050+ gs->g2d_surface.base.height = buffer->height;
1051+ gs->g2d_surface.base.rot = G2D_ROTATION_0;
1052+ gs->g2d_surface.base.clrcolor = 0xFF400000;
1053+ gs->g2d_surface.tiling = G2D_LINEAR;
1054+ gs->g2d_surface.base.format = g2dFormat;
1055+}
1056+
1057+static void
1058+g2d_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
1059+{
1060+ struct g2d_surface_state *gs = get_surface_state(es);
1061+ struct wl_shm_buffer *shm_buffer;
1062+ weston_buffer_reference(&gs->buffer_ref, buffer);
1063+
1064+ if(buffer==NULL)
1065+ return;
1066+
1067+ shm_buffer = wl_shm_buffer_get(buffer->resource);
1068+
1069+ if(shm_buffer)
1070+ {
1071+ g2d_renderer_attach_shm(es, buffer, shm_buffer);
1072+ }
1073+ else
1074+ {
1075+ g2d_renderer_attach_egl(es, buffer);
1076+ }
1077+ gs->attached = 1;
1078+}
1079+
1080+static void
1081+surface_state_destroy(struct g2d_surface_state *gs, struct g2d_renderer *gr)
1082+{
1083+ wl_list_remove(&gs->surface_destroy_listener.link);
1084+ wl_list_remove(&gs->renderer_destroy_listener.link);
1085+ if(gs->surface)
1086+ gs->surface->renderer_state = NULL;
1087+
1088+ if(gs->shm_buf)
1089+ {
1090+ g2d_free(gs->shm_buf);
1091+ gs->shm_buf = NULL;
1092+ }
1093+
1094+ weston_buffer_reference(&gs->buffer_ref, NULL);
1095+ free(gs);
1096+}
1097+
1098+static void
1099+surface_state_handle_surface_destroy(struct wl_listener *listener, void *data)
1100+{
1101+ struct g2d_surface_state *gs;
1102+ struct g2d_renderer *gr;
1103+
1104+ gs = container_of(listener, struct g2d_surface_state,
1105+ surface_destroy_listener);
1106+
1107+ gr = get_renderer(gs->surface->compositor);
1108+ surface_state_destroy(gs, gr);
1109+}
1110+
1111+static void
1112+surface_state_handle_renderer_destroy(struct wl_listener *listener, void *data)
1113+{
1114+ struct g2d_surface_state *gs;
1115+ struct g2d_renderer *gr;
1116+
1117+ gr = data;
1118+
1119+ gs = container_of(listener, struct g2d_surface_state,
1120+ renderer_destroy_listener);
1121+
1122+ surface_state_destroy(gs, gr);
1123+}
1124+
1125+
1126+static int
1127+g2d_renderer_create_surface(struct weston_surface *surface)
1128+{
1129+ struct g2d_surface_state *gs;
1130+ struct g2d_renderer *gr = get_renderer(surface->compositor);
1131+
1132+ gs = zalloc(sizeof *gs);
1133+ if (gs == NULL)
1134+ return -1;
1135+
1136+ /* A buffer is never attached to solid color surfaces, yet
1137+ * they still go through texcoord computations. Do not divide
1138+ * by zero there.
1139+ */
1140+ gs->pitch = 1;
1141+
1142+ gs->surface = surface;
1143+
1144+ pixman_region32_init(&gs->texture_damage);
1145+ surface->renderer_state = gs;
1146+
1147+ gs->surface_destroy_listener.notify =
1148+ surface_state_handle_surface_destroy;
1149+ wl_signal_add(&surface->destroy_signal,
1150+ &gs->surface_destroy_listener);
1151+
1152+ gs->renderer_destroy_listener.notify =
1153+ surface_state_handle_renderer_destroy;
1154+ wl_signal_add(&gr->destroy_signal,
1155+ &gs->renderer_destroy_listener);
1156+
1157+ if (surface->buffer_ref.buffer) {
1158+ g2d_renderer_attach(surface, surface->buffer_ref.buffer);
1159+ g2d_renderer_flush_damage(surface);
1160+ }
1161+
1162+ return 0;
1163+}
1164+
1165+static void
1166+g2d_renderer_surface_set_color(struct weston_surface *surface,
1167+ float red, float green, float blue, float alpha)
1168+{
1169+ struct g2d_surface_state *gs = get_surface_state(surface);
1170+
1171+ gs->color[0] = red;
1172+ gs->color[1] = green;
1173+ gs->color[2] = blue;
1174+ gs->color[3] = alpha;
1175+}
1176+
1177+
1178+static void
1179+g2d_renderer_output_destroy(struct weston_output *output)
1180+{
1181+ struct g2d_output_state *go = get_output_state(output);
1182+ int i;
1183+
1184+ for (i = 0; i < 2; i++)
1185+ {
1186+ pixman_region32_fini(&go->buffer_damage[i]);
1187+ }
1188+
1189+ if(go->offscreen_buf)
1190+ {
1191+ g2d_free(go->offscreen_buf);
1192+ go->offscreen_buf = NULL;
1193+ }
1194+
1195+ if(go->fb_info.fb_fd)
1196+ {
1197+ close(go->fb_info.fb_fd);
1198+ go->fb_info.fb_fd = 0;
1199+ }
1200+
1201+ if(go->renderSurf)
1202+ {
1203+ free(go->renderSurf);
1204+ go->renderSurf = NULL;
1205+ }
1206+ for (i = 0; i < go->clone_display_num; i++)
1207+ {
1208+ if(go->mirror_fb_info[i].fb_fd)
1209+ {
1210+ close(go->mirror_fb_info[i].fb_fd);
1211+ go->mirror_fb_info[i].fb_fd = 0;
1212+ }
1213+ }
1214+ if(go->mirrorSurf)
1215+ {
1216+ free(go->mirrorSurf);
1217+ go->mirrorSurf = NULL;
1218+ }
1219+ if(go->mirror_fb_info)
1220+ {
1221+ free(go->mirror_fb_info);
1222+ go->mirror_fb_info = NULL;
1223+ }
1224+
1225+ free(go);
1226+}
1227+
1228+static void
1229+g2d_renderer_destroy(struct weston_compositor *ec)
1230+{
1231+ struct g2d_renderer *gr = get_renderer(ec);
1232+
1233+ wl_signal_emit(&gr->destroy_signal, gr);
1234+ g2d_close(gr->handle);
1235+#ifdef ENABLE_EGL
1236+ eglUnbindWaylandDisplayWL(gr->egl_display);
1237+ eglTerminate(gr->egl_display);
1238+ fbDestroyDisplay(gr->display);
1239+#endif
1240+ free(ec->renderer);
1241+ ec->renderer = NULL;
1242+}
1243+
1244+static int
1245+g2d_renderer_create(struct weston_compositor *ec)
1246+{
1247+ struct g2d_renderer *gr;
1248+ gr = malloc(sizeof *gr);
1249+ if (gr == NULL)
1250+ return -1;
1251+
1252+ gr->base.read_pixels = g2d_renderer_read_pixels;
1253+ gr->base.repaint_output = g2d_renderer_repaint_output;
1254+ gr->base.flush_damage = g2d_renderer_flush_damage;
1255+ gr->base.attach = g2d_renderer_attach;
1256+ gr->base.surface_set_color = g2d_renderer_surface_set_color;
1257+ gr->base.destroy = g2d_renderer_destroy;
1258+
1259+ if(g2d_open(&gr->handle))
1260+ {
1261+ weston_log("g2d_open fail.\n");
1262+ return -1;
1263+ }
1264+ ec->renderer = &gr->base;
1265+ wl_signal_init(&gr->destroy_signal);
1266+ return 0;
1267+}
1268+
1269+static int
1270+calculate_g2d_format(struct fb_var_screeninfo *varinfo, enum g2d_format *g2dFormat)
1271+{
1272+ /* Get the color format. */
1273+ switch (varinfo->green.length)
1274+ {
1275+ case 6:
1276+ *g2dFormat= G2D_RGB565;
1277+ break;
1278+
1279+ case 8:
1280+ if (varinfo->blue.offset == 0)
1281+ {
1282+ *g2dFormat = (varinfo->transp.length == 0) ? G2D_BGRX8888 : G2D_BGRA8888;
1283+ }
1284+ else
1285+ {
1286+ *g2dFormat = (varinfo->transp.length == 0) ? G2D_RGBX8888 : G2D_RGBA8888;
1287+ }
1288+ break;
1289+
1290+ default:
1291+ *g2dFormat = -1;
1292+ break;
1293+ }
1294+ return 0;
1295+}
1296+
1297+static int
1298+get_G2dSurface_from_screeninfo(struct fb_screeninfo *info, struct g2d_surfaceEx* g2dSurface)
1299+{
1300+ if(info && g2dSurface)
1301+ {
1302+ g2dSurface->base.planes[0] = info->physical;
1303+ g2dSurface->base.left = 0;
1304+ g2dSurface->base.top = 0;
1305+ g2dSurface->base.right = info->x_resolution;
1306+ g2dSurface->base.bottom = info->y_resolution;
1307+ g2dSurface->base.stride = info->stride;
1308+ g2dSurface->base.width = info->x_resolution;
1309+ g2dSurface->base.height = info->y_resolution;
1310+ g2dSurface->base.format = info->pixel_format;
1311+ g2dSurface->base.rot = G2D_ROTATION_0;
1312+ g2dSurface->base.clrcolor = 0xFF400000;
1313+ g2dSurface->tiling = G2D_LINEAR;
1314+ return 0;
1315+ }
1316+ return -1;
1317+}
1318+
1319+static int
1320+fb_query_screen_info(struct g2d_output_state *output, int fd,
1321+ struct fb_screeninfo *info)
1322+{
1323+ struct g2d_output_state *go = output;
1324+ struct fb_var_screeninfo *varinfo = &info->varinfo;
1325+ struct fb_fix_screeninfo *fixinfo = &info->fixinfo;
1326+
1327+ /* Probe the device for screen information. */
1328+ if (ioctl(fd, FBIOGET_VSCREENINFO, varinfo) < 0) {
1329+ return -1;
1330+ }
1331+
1332+ if(go->nNumBuffers > 1){
1333+ varinfo->yres_virtual = varinfo->yres * go->nNumBuffers;
1334+ if (ioctl(fd, FBIOPUT_VSCREENINFO, varinfo) < 0)
1335+ return -1;
1336+ }
1337+
1338+ if (ioctl(fd, FBIOGET_FSCREENINFO, fixinfo) < 0 ||
1339+ ioctl(fd, FBIOGET_VSCREENINFO, varinfo) < 0){
1340+ return -1;
1341+ }
1342+ /* Store the pertinent data. */
1343+ info->x_resolution = varinfo->xres;
1344+ info->y_resolution = varinfo->yres;
1345+ info->physical = fixinfo->smem_start;
1346+ info->buffer_length = fixinfo->smem_len;
1347+ info->stride = fixinfo->line_length / (varinfo->bits_per_pixel >> 3);
1348+ info->stride_bytes = fixinfo->line_length;
1349+ calculate_g2d_format(varinfo, &info->pixel_format);
1350+
1351+ if (info->pixel_format < 0) {
1352+ weston_log("Frame buffer uses an unsupported format.\n");
1353+ return -1;
1354+ }
1355+
1356+ return 0;
1357+}
1358+
1359+static int
1360+fb_frame_buffer_open(struct g2d_output_state *output, const char *fb_dev,
1361+ struct fb_screeninfo *screen_info)
1362+{
1363+ /* Open the frame buffer device. */
1364+ screen_info->fb_fd = open(fb_dev, O_RDWR | O_CLOEXEC);
1365+ if (screen_info->fb_fd < 0) {
1366+ weston_log("Failed to open frame buffer device%s \n", fb_dev);
1367+ return -1;
1368+ }
1369+
1370+ /* Grab the screen info. */
1371+ if (fb_query_screen_info(output, screen_info->fb_fd, screen_info) < 0) {
1372+ weston_log("Failed to get frame buffer info \n");
1373+
1374+ close(screen_info->fb_fd);
1375+ return -1;
1376+ }
1377+
1378+ return 0;
1379+}
1380+
1381+static void
1382+getBufferNumber(struct g2d_output_state *go)
1383+{
1384+ char *p = NULL;
1385+ p = getenv("FB_MULTI_BUFFER");
1386+ if (p == gcvNULL)
1387+ {
1388+ go->nNumBuffers = 1;
1389+ }
1390+ else
1391+ {
1392+ go->nNumBuffers = atoi(p);
1393+ if (go->nNumBuffers < 2)
1394+ {
1395+ go->nNumBuffers = 1;
1396+ }
1397+ else if(go->nNumBuffers >= 2)
1398+ {
1399+ go->nNumBuffers = 2;
1400+ go->activebuffer = 1;
1401+ }
1402+ }
1403+ weston_log("FB_MULTI_BUFFER = %d\n", go->nNumBuffers);
1404+}
1405+
1406+static int
1407+g2d_renderer_surface_create(struct g2d_output_state *go, struct g2d_renderer *gr, const char *device)
1408+{
1409+ int i = 0;
1410+ int offset = 0;
1411+ weston_log("Opend device=%s\n", device);
1412+ if(fb_frame_buffer_open(go, device, &go->fb_info) < 0)
1413+ {
1414+ weston_log("Open frame buffer failed.\n");
1415+ return -1;
1416+ }
1417+ go->renderSurf = zalloc(sizeof(struct g2d_surfaceEx) * go->nNumBuffers);
1418+ offset = go->fb_info.stride_bytes * go->fb_info.y_resolution;
1419+ for(i = 0; i < go->nNumBuffers; i++)
1420+ {
1421+ get_G2dSurface_from_screeninfo(&go->fb_info, &go->renderSurf[i]);
1422+ go->renderSurf[i].base.planes[0] = go->fb_info.physical
1423+ + (offset * i);
1424+ g2d_clear(gr->handle, &go->renderSurf[i].base);
1425+ }
1426+
1427+ if(go->nNumBuffers == 1)
1428+ {
1429+ go->offscreenSurface = (go->renderSurf[go->activebuffer]);
1430+ go->offscreen_buf = g2d_alloc(go->fb_info.buffer_length, 0);
1431+ go->offscreenSurface.base.planes[0] = go->offscreen_buf->buf_paddr;
1432+ g2d_clear(gr->handle, &go->offscreenSurface.base);
1433+ }
1434+ return 0;
1435+}
1436+
1437+static int
1438+g2d_renderer_output_create(struct weston_output *output, struct wl_display *wl_display, const char *device)
1439+
1440+ {
1441+ struct g2d_renderer *gr = get_renderer(output->compositor);
1442+ struct g2d_output_state *go;
1443+ int i;
1444+ int clone_display_num = 0;
1445+ int count = 0;
1446+ int k=0, dispCount = 0;
1447+ char displays[5][32];
1448+ weston_log("g2d_renderer_output_create device=%s\n", device);
1449+ count = strlen(device);
1450+
1451+ if(count > 0)
1452+ {
1453+ for(i= 0; i < count; i++)
1454+ {
1455+ if(device[i] == ',')
1456+ {
1457+ displays[dispCount][k] = '\0';
1458+ dispCount++;
1459+ k = 0;
1460+ continue;
1461+ }
1462+ else if(device[i] != ' ')
1463+ {
1464+ displays[dispCount][k++] = device[i];
1465+ }
1466+ }
1467+ displays[dispCount][k] = '\0';
1468+ clone_display_num = dispCount++;
1469+ weston_log("clone_display_num = %d\n", clone_display_num);
1470+ }
1471+ else
1472+ {
1473+ weston_log("Invalid device name\n");
1474+ return -1;
1475+ }
1476+
1477+ go = zalloc(sizeof *go);
1478+ if (go == NULL)
1479+ return -1;
1480+ go->clone_display_num = clone_display_num;
1481+ output->renderer_state = go;
1482+#ifdef ENABLE_EGL
1483+ gr->wl_display = wl_display;
1484+ gr->display = fbGetDisplay(wl_display);
1485+ gr->egl_display = eglGetDisplay(gr->display);
1486+ eglBindWaylandDisplayWL(gr->egl_display, wl_display);
1487+#endif
1488+ getBufferNumber(go);
1489+
1490+ if(g2d_renderer_surface_create(go, gr, displays[0]) < 0)
1491+ {
1492+ weston_log("Create Render surface failed.\n");
1493+ return -1;
1494+ }
1495+
1496+ if(go->clone_display_num)
1497+ {
1498+ go->mirrorSurf = zalloc(sizeof(struct g2d_surfaceEx) * clone_display_num);
1499+ go->mirror_fb_info = zalloc(sizeof(struct fb_screeninfo) * clone_display_num);
1500+ if(go->mirrorSurf == NULL || go->mirror_fb_info == NULL)
1501+ return -1;
1502+
1503+ for(i = 0; i < clone_display_num; i++)
1504+ {
1505+ if(fb_frame_buffer_open(go, displays[i + 1], &go->mirror_fb_info[i]) < 0)
1506+ {
1507+ weston_log("Open frame buffer failed.\n");
1508+ return -1;
1509+ }
1510+ get_G2dSurface_from_screeninfo(&go->mirror_fb_info[i], &go->mirrorSurf[i]);
1511+ go->mirrorSurf[i].base.planes[0] = go->mirror_fb_info[i].physical;
1512+ g2d_clear(gr->handle, &go->mirrorSurf[i].base);
1513+ }
1514+ }
1515+ g2d_finish(gr->handle);
1516+ for (i = 0; i < BUFFER_DAMAGE_COUNT; i++)
1517+ pixman_region32_init(&go->buffer_damage[i]);
1518+ return 0;
1519+ }
1520+
1521+ WL_EXPORT struct g2d_renderer_interface g2d_renderer_interface = {
1522+ .create = g2d_renderer_create,
1523+ .output_create = g2d_renderer_output_create,
1524+ .output_destroy = g2d_renderer_output_destroy,
1525+};
1526diff --git a/src/g2d-renderer.h b/src/g2d-renderer.h
1527new file mode 100644
1528index 0000000..fc4ca49
1529--- /dev/null
1530+++ b/src/g2d-renderer.h
1531@@ -0,0 +1,47 @@
1532+/*
1533+ * Copyright (c) 2015 Freescale Semiconductor, Inc.
1534+ * Copyright © 2013 Vasily Khoruzhick <anarsoul@gmail.com>
1535+ *
1536+ * Permission is hereby granted, free of charge, to any person obtaining
1537+ * a copy of this software and associated documentation files (the
1538+ * "Software"), to deal in the Software without restriction, including
1539+ * without limitation the rights to use, copy, modify, merge, publish,
1540+ * distribute, sublicense, and/or sell copies of the Software, and to
1541+ * permit persons to whom the Software is furnished to do so, subject to
1542+ * the following conditions:
1543+ *
1544+ * The above copyright notice and this permission notice (including the
1545+ * next paragraph) shall be included in all copies or substantial
1546+ * portions of the Software.
1547+ *
1548+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1549+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1550+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1551+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
1552+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1553+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1554+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1555+ * SOFTWARE.
1556+ */
1557+#ifndef __g2d_renderer_h_
1558+#define __g2d_renderer_h_
1559+
1560+#include "compositor.h"
1561+
1562+#ifdef ENABLE_EGL
1563+#include <EGL/egl.h>
1564+#include <EGL/eglext.h>
1565+#endif
1566+
1567+struct g2d_renderer_interface {
1568+
1569+ int (*create)(struct weston_compositor *ec);
1570+
1571+ int (*output_create)(struct weston_output *output,
1572+ struct wl_display *wl_display,
1573+ const char *device);
1574+
1575+ void (*output_destroy)(struct weston_output *output);
1576+};
1577+
1578+#endif
1579diff --git a/src/main.c b/src/main.c
1580index 3279ac6..5d0bdc4 100644
1581--- a/src/main.c
1582+++ b/src/main.c
1583@@ -285,7 +285,8 @@ usage(int error_code)
1584 "Options for fbdev-backend.so:\n\n"
1585 " --tty=TTY\t\tThe tty to use\n"
1586 " --device=DEVICE\tThe framebuffer device to use\n"
1587- " --use-gl\t\tUse the GL renderer\n\n");
1588+ " --use-gl=1\t\tUse the GL renderer\n"
1589+ " --use-g2d=1\t\tUse the g2d renderer\n\n");
1590 #endif
1591
1592 #if defined(BUILD_HEADLESS_COMPOSITOR)
1593@@ -868,7 +869,8 @@ load_fbdev_backend(struct weston_compositor *c, char const * backend,
1594 const struct weston_option fbdev_options[] = {
1595 { WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
1596 { WESTON_OPTION_STRING, "device", 0, &config.device },
1597- { WESTON_OPTION_BOOLEAN, "use-gl", 0, &config.use_gl },
1598+ { WESTON_OPTION_INTEGER, "use-gl", 0, &config.use_gl },
1599+ { WESTON_OPTION_INTEGER, "use-g2d", 0, &config.use_g2d },
1600 };
1601
1602 parse_options(fbdev_options, ARRAY_LENGTH(fbdev_options), argc, argv);
1603--
16042.7.4
1605