From 2a24c62ef00d1b08974bd8f07e277695ac2911fa Mon Sep 17 00:00:00 2001 From: Yong Gan Date: Thu, 22 May 2014 15:26:31 +0800 Subject: [PATCH 2/3] ENGR00314805-2 Add Vivante GAL2D support Add Vivante GAL2D compositor support. Upstream-Status: Pending [DATE]05-22-2014 Signed-off-by Yong Gan --- Makefile.am | 13 + src/compositor-fbdev.c | 110 ++++- src/gal2d-renderer.c | 1187 ++++++++++++++++++++++++++++++++++++++++++++++++ src/gal2d-renderer.h | 41 ++ 4 files changed, 1337 insertions(+), 14 deletions(-) create mode 100644 src/gal2d-renderer.c create mode 100644 src/gal2d-renderer.h diff --git a/Makefile.am b/Makefile.am index 343adc6..2bccfe9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -162,6 +162,19 @@ gl_renderer_la_SOURCES = \ src/gl-renderer.c \ src/vertex-clipping.c \ src/vertex-clipping.h + +module_LTLIBRARIES += gal2d-renderer.la +gal2d_renderer_la_LDFLAGS = -module -avoid-version +gal2d_renderer_la_LIBADD = $(COMPOSITOR_LIBS) $(EGL_LIBS) +gal2d_renderer_la_CFLAGS = \ + $(COMPOSITOR_CFLAGS) \ + $(EGL_CFLAGS) \ + $(GCC_CFLAGS) +gal2d_renderer_la_SOURCES = \ + src/gal2d-renderer.h \ + src/gal2d-renderer.c \ + src/vertex-clipping.c \ + src/vertex-clipping.h endif if ENABLE_X11_COMPOSITOR diff --git a/src/compositor-fbdev.c b/src/compositor-fbdev.c index 3db1d17..a3d32e5 100644 --- a/src/compositor-fbdev.c +++ b/src/compositor-fbdev.c @@ -44,6 +44,7 @@ #include "pixman-renderer.h" #include "udev-input.h" #include "gl-renderer.h" +#include "gal2d-renderer.h" struct fbdev_compositor { struct weston_compositor base; @@ -52,6 +53,7 @@ struct fbdev_compositor { struct udev *udev; struct udev_input input; int use_pixman; + int use_gal2d; struct wl_listener session_listener; EGLNativeDisplayType display; }; @@ -97,9 +99,11 @@ struct fbdev_parameters { int tty; char *device; int use_gl; + int use_gal2d; }; struct gl_renderer_interface *gl_renderer; +struct gal2d_renderer_interface *gal2d_renderer; static const char default_seat[] = "seat0"; @@ -502,7 +506,7 @@ static void fbdev_output_disable(struct weston_output *base); static int fbdev_output_create(struct fbdev_compositor *compositor, - const char *device) + int x, int y, const char *device) { struct fbdev_output *output; pixman_transform_t transform; @@ -512,7 +516,8 @@ fbdev_output_create(struct fbdev_compositor *compositor, unsigned int bytes_per_pixel; struct wl_event_loop *loop; - weston_log("Creating fbdev output.\n"); + + weston_log("Creating fbdev output. %s x=%d y=%d\n", device, x, y); output = calloc(1, sizeof *output); if (!output) @@ -559,7 +564,7 @@ fbdev_output_create(struct fbdev_compositor *compositor, output->base.model = output->fb_info.id; weston_output_init(&output->base, &compositor->base, - 0, 0, output->fb_info.width_mm, + x, y, output->fb_info.width_mm, output->fb_info.height_mm, WL_OUTPUT_TRANSFORM_NORMAL, 1); @@ -629,8 +634,33 @@ fbdev_output_create(struct fbdev_compositor *compositor, if (compositor->use_pixman) { if (pixman_renderer_output_create(&output->base) < 0) goto out_shadow_surface; - } else { - setenv("HYBRIS_EGLPLATFORM", "wayland", 1); + } + else if(compositor->use_gal2d) { + + char* fbenv = getenv("FB_FRAMEBUFFER_0"); + setenv("FB_FRAMEBUFFER_0", device, 1); + output->display = fbGetDisplay(compositor->base.wl_display); + if (output->display == NULL) { + fprintf(stderr, "failed to get display\n"); + return 0; + } + + output->window = fbCreateWindow(output->display, -1, -1, 0, 0); + if (output->window == NULL) { + fprintf(stderr, "failed to create window\n"); + return 0; + } + setenv("FB_FRAMEBUFFER_0", fbenv, 1); + + if (gal2d_renderer->output_create(&output->base, + output->display, + (NativeWindowType)output->window) < 0) { + weston_log("gal_renderer_output_create failed.\n"); + goto out_shadow_surface; + } + + } + else { output->window = fbCreateWindow(compositor->display, -1, -1, 0, 0); if (output->window == NULL) { fprintf(stderr, "failed to create window\n"); @@ -698,7 +728,11 @@ fbdev_output_destroy(struct weston_output *base) free(output->shadow_buf); output->shadow_buf = NULL; } - } else { + } + else if (compositor->use_gal2d) { + gal2d_renderer->output_destroy(base); + } + else { gl_renderer->output_destroy(base); } @@ -761,7 +795,7 @@ fbdev_output_reenable(struct fbdev_compositor *compositor, * are re-initialised. */ device = output->device; fbdev_output_destroy(base); - fbdev_output_create(compositor, device); + fbdev_output_create(compositor, 0, 0, device); return 0; } @@ -914,7 +948,10 @@ fbdev_compositor_create(struct wl_display *display, int *argc, char *argv[], compositor->base.restore = fbdev_restore; compositor->prev_state = WESTON_COMPOSITOR_ACTIVE; - compositor->use_pixman = !param->use_gl; + compositor->use_gal2d = param->use_gal2d; + weston_log("compositor->use_gal2d=%d\n", compositor->use_gal2d); + if(param->use_gl == 0 && param->use_gal2d == 0) + compositor->use_pixman = 1; for (key = KEY_F1; key < KEY_F9; key++) weston_compositor_add_key_binding(&compositor->base, key, @@ -924,7 +961,50 @@ fbdev_compositor_create(struct wl_display *display, int *argc, char *argv[], if (compositor->use_pixman) { if (pixman_renderer_init(&compositor->base) < 0) goto out_launcher; - } else { + } + else if (compositor->use_gal2d) { + int x = 0, y = 0; + int i=0; + int count = 0; + int k=0, dispCount = 0; + char displays[5][32]; + gal2d_renderer = weston_load_module("gal2d-renderer.so", + "gal2d_renderer_interface"); + if (!gal2d_renderer) { + weston_log("could not load gal2d renderer\n"); + goto out_launcher; + } + + if (gal2d_renderer->create(&compositor->base) < 0) { + weston_log("gal2d_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; ibase.output_list.prev, + struct weston_output, + link)->width; + } + } + else { gl_renderer = weston_load_module("gl-renderer.so", "gl_renderer_interface"); if (!gl_renderer) { @@ -945,9 +1025,9 @@ fbdev_compositor_create(struct wl_display *display, int *argc, char *argv[], goto out_launcher; } } - - if (fbdev_output_create(compositor, param->device) < 0) - goto out_pixman; + if(!compositor->use_gal2d) + if (fbdev_output_create(compositor, 0, 0, param->device) < 0) + goto out_pixman; udev_input_init(&compositor->input, &compositor->base, compositor->udev, seat_id); @@ -980,13 +1060,15 @@ backend_init(struct wl_display *display, int *argc, char *argv[], struct fbdev_parameters param = { .tty = 0, /* default to current tty */ .device = "/dev/fb0", /* default frame buffer */ - .use_gl = 0, + .use_gl = 1, + .use_gal2d = 0, }; const struct weston_option fbdev_options[] = { { WESTON_OPTION_INTEGER, "tty", 0, ¶m.tty }, { WESTON_OPTION_STRING, "device", 0, ¶m.device }, - { WESTON_OPTION_BOOLEAN, "use-gl", 0, ¶m.use_gl }, + { WESTON_OPTION_INTEGER, "use-gl", 0, ¶m.use_gl }, + { WESTON_OPTION_INTEGER, "use-gal2d", 0, ¶m.use_gal2d }, }; parse_options(fbdev_options, ARRAY_LENGTH(fbdev_options), argc, argv); diff --git a/src/gal2d-renderer.c b/src/gal2d-renderer.c new file mode 100644 index 0000000..c651573 --- /dev/null +++ b/src/gal2d-renderer.c @@ -0,0 +1,1187 @@ +/* + * Copyright (c) 2014 Freescale Semiconductor, Inc. + * Copyright © 2012 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include "compositor.h" +#include "gal2d-renderer.h" +#include "vertex-clipping.h" +#include "HAL/gc_hal.h" +#include "HAL/gc_hal_raster.h" +#include "HAL/gc_hal_eglplatform.h" + +#define galONERROR(x) if(status < 0) printf("Error in function %s\n", __func__); + + +struct gal2d_output_state { + + int current_buffer; + pixman_region32_t buffer_damage[2]; + EGLNativeDisplayType display; + gcoSURF* renderSurf; + gctUINT32 nNumBuffers; + int activebuffer; + gcoSURF offscreenSurface; + gceSURF_FORMAT format; + gcoSURF tempSurf; +}; + +struct gal2d_surface_state { + float color[4]; + struct weston_buffer_reference buffer_ref; + int pitch; /* in pixels */ + pixman_region32_t texture_damage; + gcoSURF gco_Surface; + + struct weston_surface *surface; + struct wl_listener surface_destroy_listener; + struct wl_listener renderer_destroy_listener; +}; + +struct gal2d_renderer { + struct weston_renderer base; + struct wl_signal destroy_signal; + gcoOS gcos; + gcoHAL gcoHal; + gco2D gcoEngine2d; + gctPOINTER localInfo; +}; + +static int +gal2d_renderer_create_surface(struct weston_surface *surface); + +static inline struct gal2d_surface_state * +get_surface_state(struct weston_surface *surface) +{ + if (!surface->renderer_state) + gal2d_renderer_create_surface(surface); + return (struct gal2d_surface_state *)surface->renderer_state; +} + +static inline struct gal2d_renderer * +get_renderer(struct weston_compositor *ec) +{ + return (struct gal2d_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 gal2d_output_state * +get_output_state(struct weston_output *output) +{ + return (struct gal2d_output_state *)output->renderer_state; +} + +static gctUINT32 +galGetStretchFactor(gctINT32 SrcSize, gctINT32 DestSize) +{ + gctUINT stretchFactor; + if ( (SrcSize > 0) && (DestSize > 1) ) + { + stretchFactor = ((SrcSize - 1) << 16) / (DestSize - 1); + } + else + { + stretchFactor = 0; + } + return stretchFactor; +} + +static gceSTATUS +galGetStretchFactors( + IN gcsRECT_PTR SrcRect, + IN gcsRECT_PTR DestRect, + OUT gctUINT32 * HorFactor, + OUT gctUINT32 * VerFactor + ) +{ + if (HorFactor != gcvNULL) + { + gctINT32 src, dest; + + /* Compute width of rectangles. */ + gcmVERIFY_OK(gcsRECT_Width(SrcRect, &src)); + gcmVERIFY_OK(gcsRECT_Width(DestRect, &dest)); + + /* Compute and return horizontal stretch factor. */ + *HorFactor = galGetStretchFactor(src, dest); + } + + if (VerFactor != gcvNULL) + { + gctINT32 src, dest; + + /* Compute height of rectangles. */ + gcmVERIFY_OK(gcsRECT_Height(SrcRect, &src)); + gcmVERIFY_OK(gcsRECT_Height(DestRect, &dest)); + + /* Compute and return vertical stretch factor. */ + *VerFactor = galGetStretchFactor(src, dest); + } + /* Success. */ + return gcvSTATUS_OK; +} + +static gceSTATUS +gal2d_getSurfaceFormat(halDISPLAY_INFO info, gceSURF_FORMAT * Format) +{ + /* Get the color format. */ + switch (info.greenLength) + { + case 4: + if (info.blueOffset == 0) + { + *Format = (info.alphaLength == 0) ? gcvSURF_X4R4G4B4 : gcvSURF_A4R4G4B4; + } + else + { + *Format = (info.alphaLength == 0) ? gcvSURF_X4B4G4R4 : gcvSURF_A4B4G4R4; + } + break; + + case 5: + if (info.blueOffset == 0) + { + *Format = (info.alphaLength == 0) ? gcvSURF_X1R5G5B5 : gcvSURF_A1R5G5B5; + } + else + { + *Format = (info.alphaLength == 0) ? gcvSURF_X1B5G5R5 : gcvSURF_A1B5G5R5; + } + break; + + case 6: + *Format = gcvSURF_R5G6B5; + break; + + case 8: + if (info.blueOffset == 0) + { + *Format = (info.alphaLength == 0) ? gcvSURF_X8R8G8B8 : gcvSURF_A8R8G8B8; + } + else + { + *Format = (info.alphaLength == 0) ? gcvSURF_X8B8G8R8 : gcvSURF_A8B8G8R8; + } + break; + + default: + /* Unsupported color depth. */ + return gcvSTATUS_INVALID_ARGUMENT; + } + /* Success. */ + return gcvSTATUS_OK; +} + +static gceSTATUS galIsYUVFormat(IN gceSURF_FORMAT Format) +{ + switch (Format) + { + case gcvSURF_YUY2: + case gcvSURF_UYVY: + case gcvSURF_I420: + case gcvSURF_YV12: + case gcvSURF_NV16: + case gcvSURF_NV12: + case gcvSURF_NV61: + case gcvSURF_NV21: + + return gcvSTATUS_TRUE; + + default: + return gcvSTATUS_FALSE; + } +} + +static gceSTATUS galQueryUVStride( + IN gceSURF_FORMAT Format, + IN gctUINT32 yStride, + OUT gctUINT32_PTR uStride, + OUT gctUINT32_PTR vStride + ) +{ + switch (Format) + { + case gcvSURF_YUY2: + case gcvSURF_UYVY: + *uStride = *vStride = 0; + break; + + case gcvSURF_I420: + case gcvSURF_YV12: + *uStride = *vStride = yStride / 2; + break; + + case gcvSURF_NV16: + case gcvSURF_NV12: + case gcvSURF_NV61: + case gcvSURF_NV21: + + *uStride = yStride; + *vStride = 0; + break; + + default: + return gcvSTATUS_NOT_SUPPORTED; + } + + return gcvSTATUS_OK; +} + +static int +make_current(struct gal2d_renderer *gr, gcoSURF surface) +{ + gceSTATUS status = gcvSTATUS_OK; + gctUINT width = 0; + gctUINT height = 0; + gctINT stride = 0; + gctUINT32 physical; + gctPOINTER va =0; + + if(!surface) + goto OnError; + + + gcmONERROR(gcoSURF_GetAlignedSize(surface, &width, &height, &stride)); + + gcmONERROR(gcoSURF_Lock(surface, &physical, (gctPOINTER *)&va)); + + gcmONERROR(gco2D_SetTargetEx(gr->gcoEngine2d, physical, stride, + gcvSURF_0_DEGREE, width, height)); + + gcmONERROR(gcoSURF_Unlock(surface, (gctPOINTER *)&va)); + +OnError: + galONERROR(status); + return status; +} + +static gceSTATUS +gal2d_clear(struct weston_output *base) +{ + struct gal2d_renderer *gr = get_renderer(base->compositor); + struct gal2d_output_state *go = get_output_state(base); + gceSTATUS status = gcvSTATUS_OK; + + gctINT stride = 0; + gctUINT width = 0, height = 0; + gcsRECT dstRect = {0}; + gcmONERROR(gcoSURF_GetAlignedSize(go->renderSurf[go->activebuffer], + &width, &height, &stride)); + dstRect.right = width; + dstRect.bottom = height; + gcmONERROR(gco2D_SetSource(gr->gcoEngine2d, &dstRect)); + gcmONERROR(gco2D_SetClipping(gr->gcoEngine2d, &dstRect)); + gcmONERROR(gco2D_Clear(gr->gcoEngine2d, 1, &dstRect, 0xff0000ff, 0xCC, 0xCC, go->format)); + + gcmONERROR(gcoHAL_Commit(gr->gcoHal, gcvFALSE)); + +OnError: + galONERROR(status); + + return status; +} + +static gcoSURF getSurfaceFromShm(struct weston_surface *es, struct weston_buffer *buffer) +{ + struct gal2d_renderer *gr = get_renderer(es->compositor); + + gcoSURF surface = 0; + gceSURF_FORMAT format; + gcePOOL pool = gcvPOOL_DEFAULT; + + if (wl_shm_buffer_get_format(buffer->shm_buffer) == WL_SHM_FORMAT_XRGB8888) + format = gcvSURF_X8R8G8B8; + else + format = gcvSURF_A8R8G8B8; + + if(buffer->width == ((buffer->width + 0x7) & ~0x7)) + { + pool = gcvPOOL_USER; + } + + gcmVERIFY_OK(gcoSURF_Construct(gr->gcoHal, + (gctUINT) buffer->width, + (gctUINT) buffer->height, + 1, gcvSURF_BITMAP, + format, pool, &surface)); + + if(pool == gcvPOOL_USER) + { + gcmVERIFY_OK(gcoSURF_MapUserSurface(surface, 1, + (gctPOINTER)wl_shm_buffer_get_data(buffer->shm_buffer), gcvINVALID_ADDRESS)); + } + + return surface; +} + +static int +gal2dBindBuffer(struct weston_surface* es) +{ + struct gal2d_surface_state *gs = get_surface_state(es); + gceSTATUS status = gcvSTATUS_OK; + gcoSURF surface = gs->gco_Surface; + struct weston_buffer *buffer = gs->buffer_ref.buffer; + gcePOOL pool = gcvPOOL_DEFAULT; + gctUINT64 node = 0; + gctUINT bytes; + + gcmVERIFY_OK(gcoSURF_QueryVidMemNode(surface, &node, + &pool, &bytes)); + + if(pool != gcvPOOL_USER) + { + gctUINT alignedWidth; + gctPOINTER logical = (gctPOINTER)wl_shm_buffer_get_data(buffer->shm_buffer); + gctPOINTER va =0; + + + gcmVERIFY_OK(gcoSURF_GetAlignedSize(surface, &alignedWidth, gcvNULL, gcvNULL)); + gcmVERIFY_OK(gcoSURF_Lock(surface, gcvNULL, (gctPOINTER *)&va)); + + if(alignedWidth == (unsigned int)buffer->width) + { + int size = wl_shm_buffer_get_stride(buffer->shm_buffer)*buffer->height; + memcpy(va, logical, size); + } + else + { + int i, j; + for (i = 0; i < buffer->height; i++) + { + for (j = 0; j < buffer->width; j++) + { + gctUINT dstOff = i * alignedWidth + j; + gctUINT srcOff = (i * buffer->width + j); + + memcpy(va + dstOff * 4, logical + srcOff * 4, 4); + } + } + } + gcmVERIFY_OK(gcoSURF_Unlock(surface, (gctPOINTER)va)); + } + + return status; +} + +static void +gal2d_flip_surface(struct weston_output *output) +{ + struct gal2d_renderer *gr = get_renderer(output->compositor); + struct gal2d_output_state *go = get_output_state(output); + + if(go->nNumBuffers > 1) + { + gctUINT Offset; + gctINT X; + gctINT Y; + gcmVERIFY_OK(gcoHAL_Commit(gr->gcoHal, gcvTRUE)); + + gcmVERIFY_OK(gcoOS_GetDisplayBackbuffer(go->display, gcvNULL, + gcvNULL, gcvNULL, &Offset, &X, &Y)); + + gcmVERIFY_OK(gcoOS_SetDisplayVirtual(go->display, gcvNULL, + Offset, X, Y)); + + go->activebuffer = (go->activebuffer+1) % go->nNumBuffers; + } +} + +static int +update_surface(struct weston_output *output) +{ + struct gal2d_renderer *gr = get_renderer(output->compositor); + struct gal2d_output_state *go = get_output_state(output); + gceSTATUS status = gcvSTATUS_OK; + + if(go->offscreenSurface && go->nNumBuffers == 1) + { + make_current(gr, go->renderSurf[go->activebuffer]); + + gctUINT srcWidth = 0; + gctUINT srcHeight = 0; + gctINT srcStride = 0; + gceSURF_FORMAT srcFormat;; + gcsRECT dstRect = {0}; + gcoSURF srcSurface = go->offscreenSurface; + gctUINT32 physical; + gctPOINTER va =0; + + gcmONERROR(gcoSURF_GetAlignedSize(srcSurface, &srcWidth, &srcHeight, &srcStride)); + gcmONERROR(gcoSURF_GetFormat(srcSurface, gcvNULL, &srcFormat)); + gcmONERROR(gcoSURF_Lock(srcSurface, &physical, (gctPOINTER *)&va)); + gcmONERROR(gco2D_SetColorSource(gr->gcoEngine2d, physical, srcStride, srcFormat, + gcvFALSE, srcWidth, gcvFALSE, gcvSURF_OPAQUE, 0)); + + dstRect.left = 0; + dstRect.top = 0; + dstRect.right = srcWidth; + dstRect.bottom = srcHeight; + + gcmONERROR(gco2D_SetSource(gr->gcoEngine2d, &dstRect)); + gcmONERROR(gco2D_SetClipping(gr->gcoEngine2d, &dstRect)); + gcmONERROR(gco2D_Blit(gr->gcoEngine2d, 1, &dstRect, 0xCC, 0xCC, go->format)); + gcmONERROR(gcoSURF_Unlock(srcSurface, (gctPOINTER *)&va)); + gcmONERROR(gcoHAL_Commit(gr->gcoHal, gcvFALSE)); + } + + gal2d_flip_surface(output); + +OnError: + galONERROR(status); + return status; + } + +static int +use_output(struct weston_output *output) +{ + struct gal2d_output_state *go = get_output_state(output); + struct gal2d_renderer *gr = get_renderer(output->compositor); + gceSTATUS status = gcvSTATUS_OK; + + gcoSURF surface; + surface = go->nNumBuffers > 1 ? + go->renderSurf[go->activebuffer] : + go->offscreenSurface; /*go->renderSurf[0];*/ + make_current(gr, surface); + return status; +} + +static int +gal2d_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 gal2d_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 gal2d_output_state *go, pixman_region32_t *region, + pixman_region32_t *surf_region){ + + struct gal2d_renderer *gr = get_renderer(ev->surface->compositor); + struct gal2d_surface_state *gs = get_surface_state(ev->surface); + + pixman_box32_t *rects, *surf_rects, *bb_rects; + int i, j, nrects, nsurf, nbb=0; + gceSTATUS status = gcvSTATUS_OK; + gcoSURF srcSurface = gs->gco_Surface; + gcsRECT srcRect = {0}; + gcsRECT dstrect = {0}; + gctUINT32 horFactor, verFactor; + int useStretch =1; + int useFilterBlit = 0; + gctUINT srcWidth = 0; + gctUINT srcHeight = 0; + gctUINT32 srcStride[3]; + gceSURF_FORMAT srcFormat;; + gctUINT32 srcPhyAddr[3]; + gctUINT32 dstPhyAddr[3]; + gctUINT dstWidth = 0; + gctUINT dstHeight = 0; + gctUINT32 dstStrides[3]; + gcoSURF dstsurface; + int geoWidth = ev->surface->width; + int geoheight = ev->surface->height; + + bb_rects = pixman_region32_rectangles(&ev->transform.boundingbox, &nbb); + + if(!srcSurface || nbb <= 0) + goto OnError; + rects = pixman_region32_rectangles(region, &nrects); + surf_rects = pixman_region32_rectangles(surf_region, &nsurf); + + gcmVERIFY_OK(gcoSURF_GetAlignedSize(srcSurface, &srcWidth, &srcHeight, (gctINT *)&srcStride[0])); + + gcmVERIFY_OK(gcoSURF_GetFormat(srcSurface, gcvNULL, &srcFormat)); + + if(galIsYUVFormat(srcFormat) == gcvSTATUS_TRUE) + { + useFilterBlit = 1; + } + + gcmVERIFY_OK(gcoSURF_Lock(srcSurface, &srcPhyAddr[0], gcvNULL)); + + gcmVERIFY_OK(gcoSURF_Unlock(srcSurface, gcvNULL)); + + srcRect.left = ev->geometry.x < 0.0 ? gal2d_int_from_double(fabsf(ev->geometry.x)) : 0; + srcRect.top = 0; /*es->geometry.y < 0.0 ? gal2d_int_from_double(fabsf(es->geometry.y)) : 0;*/ + srcRect.right = ev->surface->width; + srcRect.bottom = ev->surface->height; + + if(useFilterBlit) + { + dstsurface = go->nNumBuffers > 1 ? + go->renderSurf[go->activebuffer] : + go->offscreenSurface; + gcmVERIFY_OK(gcoSURF_GetAlignedSize(dstsurface, &dstWidth, &dstHeight, (gctINT *)&dstStrides)); + gcmVERIFY_OK(gcoSURF_Lock(dstsurface, &dstPhyAddr[0], gcvNULL)); + gcmVERIFY_OK(gcoSURF_Unlock(dstsurface, gcvNULL)); + } + else + { + gcmVERIFY_OK(gco2D_SetColorSourceEx(gr->gcoEngine2d, srcPhyAddr[0], srcStride[0], srcFormat, + gcvFALSE, srcWidth, srcHeight, gcvFALSE, gcvSURF_OPAQUE, 0)); + gcmVERIFY_OK(gco2D_SetSource(gr->gcoEngine2d, &srcRect)); + } + + 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; + + if(dstrect.right < 0 || dstrect.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; + gcsRECT clipRect = {0}; + 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 = gal2d_int_from_double(min_x); + clipRect.top = gal2d_int_from_double(min_y); + clipRect.right = gal2d_int_from_double(max_x); + clipRect.bottom = gal2d_int_from_double(max_y); + + if(output->x > 0) + { + dstrect.left = dstrect.left - output->x; + dstrect.right = dstrect.right - output->x; + clipRect.left = clipRect.left - output->x; + clipRect.right = clipRect.right - output->x; + } + + dstrect.left = (dstrect.left < 0) ? 0 : dstrect.left; + + status = gco2D_SetClipping(gr->gcoEngine2d, &clipRect); + if(status < 0) + { + weston_log("Error in gco2D_SetClipping %s\n", __func__); + goto OnError; + } + + if(useFilterBlit) + { + gctINT srcStrideNum; + gctINT srcAddressNum; + gcmVERIFY_OK(galQueryUVStride(srcFormat, srcStride[0], + &srcStride[1], &srcStride[2])); + + switch (srcFormat) + { + case gcvSURF_YUY2: + case gcvSURF_UYVY: + srcStrideNum = srcAddressNum = 1; + break; + + case gcvSURF_I420: + case gcvSURF_YV12: + srcStrideNum = srcAddressNum = 3; + break; + + case gcvSURF_NV16: + case gcvSURF_NV12: + case gcvSURF_NV61: + case gcvSURF_NV21: + srcStrideNum = srcAddressNum = 2; + break; + + default: + gcmONERROR(gcvSTATUS_NOT_SUPPORTED); + } + gco2D_FilterBlitEx2(gr->gcoEngine2d, + srcPhyAddr, srcAddressNum, + srcStride, srcStrideNum, + gcvLINEAR, srcFormat, gcvSURF_0_DEGREE, + geoWidth, geoheight, &srcRect, + dstPhyAddr, 1, + dstStrides, 1, + gcvLINEAR, go->format, gcvSURF_0_DEGREE, + dstWidth, dstHeight, + &dstrect, gcvNULL); + } + else + { + if(useStretch) + gcmVERIFY_OK(galGetStretchFactors(&srcRect, &dstrect, &horFactor, &verFactor)); + + if(verFactor == 65536 && horFactor == 65536) + { + gcmVERIFY_OK(gco2D_Blit(gr->gcoEngine2d, 1, &dstrect, + 0xCC, 0xCC, go->format)); + } + else + { + /* Program the stretch factors. */ + gcmVERIFY_OK(gco2D_SetStretchFactors(gr->gcoEngine2d, horFactor, verFactor)); + + gcmVERIFY_OK(gco2D_StretchBlit(gr->gcoEngine2d, 1, &dstrect, + 0xCC, 0xCC, go->format)); + } + } + if(status < 0) + { + printf("cr l=%d r=%d t=%d b=%d w=%d h=%d\n", + clipRect.left, clipRect.right, clipRect.top ,clipRect.bottom, + clipRect.right - clipRect.left, clipRect.bottom -clipRect.top); + printf("dr l=%d r=%d t=%d b=%d w=%d h=%d\n", + dstrect.left, dstrect.right, dstrect.top ,dstrect.bottom, + dstrect.right - dstrect.left, dstrect.bottom -dstrect.top); + printf("horFactor=%d, verFactor=%d\n",horFactor, verFactor); + + goto OnError; + } + } + status = (gcoHAL_Commit(gr->gcoHal, gcvFALSE)); + if(status < 0) + { + printf("Error in gcoHAL_Commit %s\n", __func__); + goto OnError; + } + } + +OnError: + galONERROR(status); +} + +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 gal2d_output_state *go = get_output_state(output); + /* 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); + + if (pixman_region32_not_empty(&ev->surface->opaque)) { + + repaint_region(ev, output, go, &repaint, &ev->surface->opaque); + } + + if (pixman_region32_not_empty(&surface_blend)) { + struct gal2d_renderer *gr = get_renderer(ec); + + gco2D_EnableAlphaBlend(gr->gcoEngine2d, + ev->alpha * 0xFF, ev->alpha * 0xFF, + gcvSURF_PIXEL_ALPHA_STRAIGHT, gcvSURF_PIXEL_ALPHA_STRAIGHT, + gcvSURF_GLOBAL_ALPHA_OFF, gcvSURF_GLOBAL_ALPHA_OFF, + gcvSURF_BLEND_ONE, gcvSURF_BLEND_INVERSED, + gcvSURF_COLOR_STRAIGHT, gcvSURF_COLOR_STRAIGHT); + + repaint_region(ev, output, go, &repaint, &surface_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 +gal2d_renderer_repaint_output(struct weston_output *output, + pixman_region32_t *output_damage) +{ + struct gal2d_output_state *go = get_output_state(output); + gctUINT32 i; + + if (use_output(output) < 0) + return; + + 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); + + pixman_region32_copy(&output->previous_damage, output_damage); + wl_signal_emit(&output->frame_signal, output); + + update_surface(output); + + go->current_buffer ^= 1; +} + +static void +gal2d_renderer_flush_damage(struct weston_surface *surface) +{ + struct gal2d_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)) + { + if(gs->gco_Surface==NULL) + { + gs->gco_Surface = getSurfaceFromShm(surface, buffer); + } + gal2dBindBuffer(surface); + } + else + { + gcsWL_VIV_BUFFER *vivBuffer = (gcsWL_VIV_BUFFER *)buffer; + gs->gco_Surface = vivBuffer->surface; + } + +done: + pixman_region32_fini(&gs->texture_damage); + pixman_region32_init(&gs->texture_damage); + + weston_buffer_reference(&gs->buffer_ref, NULL); +} + +static void +gal2d_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) +{ + struct gal2d_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) + { + buffer->width = wl_shm_buffer_get_width(shm_buffer); + buffer->height = wl_shm_buffer_get_height(shm_buffer); + buffer->shm_buffer = shm_buffer; + + if(gs->gco_Surface) + { + gcoSURF_Destroy(gs->gco_Surface); + gs->gco_Surface = getSurfaceFromShm(es, buffer); + } + } + else + { + gcsWL_VIV_BUFFER *vivBuffer = wl_resource_get_user_data(buffer->resource); + gs->gco_Surface = vivBuffer->surface; + + buffer->width = vivBuffer->width; + buffer->height = vivBuffer->height; + } +} + +static void +surface_state_destroy(struct gal2d_surface_state *gs, struct gal2d_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; + + weston_buffer_reference(&gs->buffer_ref, NULL); + free(gs); +} + +static void +surface_state_handle_surface_destroy(struct wl_listener *listener, void *data) +{ + struct gal2d_surface_state *gs; + struct gal2d_renderer *gr; + + gs = container_of(listener, struct gal2d_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 gal2d_surface_state *gs; + struct gal2d_renderer *gr; + + gr = data; + + gs = container_of(listener, struct gal2d_surface_state, + renderer_destroy_listener); + + surface_state_destroy(gs, gr); +} + + +static int +gal2d_renderer_create_surface(struct weston_surface *surface) +{ + struct gal2d_surface_state *gs; + struct gal2d_renderer *gr = get_renderer(surface->compositor); + + gs = calloc(1, sizeof *gs); + if (!gs) + 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) { + gal2d_renderer_attach(surface, surface->buffer_ref.buffer); + gal2d_renderer_flush_damage(surface); + } + + return 0; +} + +static void +gal2d_renderer_surface_set_color(struct weston_surface *surface, + float red, float green, float blue, float alpha) +{ + struct gal2d_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 +gal2d_renderer_output_destroy(struct weston_output *output) +{ + struct gal2d_output_state *go = get_output_state(output); + gctUINT32 i; + + if(go->nNumBuffers <= 1 ) + { + if(go->offscreenSurface) + gcmVERIFY_OK(gcoSURF_Destroy(go->offscreenSurface)); + } + + for(i=0; i < go->nNumBuffers; i++) + { + gcmVERIFY_OK(gcoSURF_Destroy(go->renderSurf[i])); + } + + free(go->renderSurf); + go->renderSurf = gcvNULL; + + free(go); +} + +static void +gal2d_renderer_destroy(struct weston_compositor *ec) +{ + struct gal2d_renderer *gr = get_renderer(ec); + + wl_signal_emit(&gr->destroy_signal, gr); + free(ec->renderer); + ec->renderer = NULL; +} + + +static int +gal2d_renderer_create(struct weston_compositor *ec) +{ + struct gal2d_renderer *gr; + gceSTATUS status = gcvSTATUS_OK; + gr = malloc(sizeof *gr); + if (gr == NULL) + return -1; + + gr->base.read_pixels = gal2d_renderer_read_pixels; + gr->base.repaint_output = gal2d_renderer_repaint_output; + gr->base.flush_damage = gal2d_renderer_flush_damage; + gr->base.attach = gal2d_renderer_attach; + gr->base.surface_set_color = gal2d_renderer_surface_set_color; + gr->base.destroy = gal2d_renderer_destroy; + + /* Construct the gcoOS object. */ + gcmONERROR(gcoOS_Construct(gcvNULL, &gr->gcos)); + + /* Construct the gcoHAL object. */ + gcmONERROR(gcoHAL_Construct(gcvNULL, gr->gcos, &gr->gcoHal)); + gcmONERROR(gcoHAL_Get2DEngine(gr->gcoHal, &gr->gcoEngine2d)); + gcmONERROR(gcoHAL_SetHardwareType(gr->gcoHal, gcvHARDWARE_2D)); + + ec->renderer = &gr->base; + wl_signal_init(&gr->destroy_signal); +OnError: + galONERROR(status); + + /* Return the status. */ + return status; + +} + +static int +gal2d_renderer_output_create(struct weston_output *output, EGLNativeDisplayType display, + EGLNativeWindowType window) + + { + struct gal2d_renderer *gr = get_renderer(output->compositor); + struct gal2d_output_state *go = calloc(1, sizeof *go); + halDISPLAY_INFO info; + gctUINT32 backOffset = 0; + gctINT width, height; + gceSTATUS status = gcvSTATUS_OK; + gctUINT32 i; + + if (!go) + return -1; + + output->renderer_state = go; + go->display = display; + gcmONERROR(gcoOS_InitLocalDisplayInfo(go->display, &gr->localInfo)); + + /* Get display information. */ + gcmONERROR(gcoOS_GetDisplayInfoEx2( + go->display, gcvNULL, gr->localInfo, + sizeof(info), &info)); + go->nNumBuffers = info.multiBuffer; + + weston_log("Number of buffers=%d\n",go->nNumBuffers); + + gcmONERROR(gal2d_getSurfaceFormat(info, &go->format)); + backOffset = (gctUINT32)(info.stride * info.height ); + + go->activebuffer = 0; + + go->renderSurf = malloc(sizeof(gcoSURF) * go->nNumBuffers); + gcoOS_GetDisplayVirtual(go->display, &width, &height); + for(i=0; i < go->nNumBuffers; i++) + { + + gcmONERROR(gcoSURF_Construct(gr->gcoHal, info.width, info.height, 1, + gcvSURF_BITMAP, go->format, gcvPOOL_USER, &go->renderSurf[i])); + + gcoSURF_MapUserSurface(go->renderSurf[i], 0,info.logical + (i * backOffset), + info.physical + (i * backOffset)); + + //Clear surfaces + make_current(gr, go->renderSurf[go->activebuffer]); + gal2d_clear(output); + gal2d_flip_surface(output); + } + if(go->nNumBuffers <= 1) + go->activebuffer = 0; + else + go->activebuffer = 1; + + if(go->nNumBuffers <= 1 ) + { + gcmVERIFY_OK(gcoSURF_Construct(gr->gcoHal, + (gctUINT) info.width, + (gctUINT) info.height, + 1, + gcvSURF_BITMAP, + go->format, + gcvPOOL_DEFAULT, + &go->offscreenSurface)); + make_current(gr, go->offscreenSurface); + gal2d_clear(output); + gal2d_flip_surface(output); + } +OnError: + galONERROR(status); + /* Return the status. */ + return status; + } + + WL_EXPORT struct gal2d_renderer_interface gal2d_renderer_interface = { + .create = gal2d_renderer_create, + .output_create = gal2d_renderer_output_create, + .output_destroy = gal2d_renderer_output_destroy, +}; diff --git a/src/gal2d-renderer.h b/src/gal2d-renderer.h new file mode 100644 index 0000000..3b89f73 --- /dev/null +++ b/src/gal2d-renderer.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 Freescale Semiconductor, Inc. + * Copyright © 2013 Vasily Khoruzhick + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __gal_2d_renderer_h_ +#define __gal_2d_renderer_h_ + +#include "compositor.h" +#include + + +struct gal2d_renderer_interface { + + int (*create)(struct weston_compositor *ec); + + int (*output_create)(struct weston_output *output, + NativeDisplayType display, + NativeWindowType window); + + void (*output_destroy)(struct weston_output *output); +}; + +#endif -- 1.7.9.5