From 807ca60da555a8fd638cb7c39825b21bb5ec855c Mon Sep 17 00:00:00 2001 From: Prabhu Sundararaj Date: Tue, 17 Sep 2013 16:46:25 -0500 Subject: [PATCH 2/2] Add support for Vivante 3D GPU Signed-off-by: Prabhu Sundararaj --- src/compositor-fbdev.c | 376 +++++++++++++++++++++++++++++++------------------ 1 file changed, 237 insertions(+), 139 deletions(-) diff --git a/src/compositor-fbdev.c b/src/compositor-fbdev.c index 9d9eff5..cb98532 100644 --- a/src/compositor-fbdev.c +++ b/src/compositor-fbdev.c @@ -44,6 +44,8 @@ #include "compositor.h" #include "launcher-util.h" #include "pixman-renderer.h" +#include +#include "gl-renderer.h" #include "udev-seat.h" struct fbdev_compositor { @@ -52,6 +54,9 @@ struct fbdev_compositor { struct udev *udev; struct tty *tty; + NativeDisplayType display; + NativeWindowType window; + int use_pixman; }; struct fbdev_screeninfo { @@ -138,63 +143,71 @@ fbdev_output_repaint(struct weston_output *base, pixman_region32_t *damage) { struct fbdev_output *output = to_fbdev_output(base); struct weston_compositor *ec = output->base.compositor; - pixman_box32_t *rects; - int nrects, i, src_x, src_y, x1, y1, x2, y2, width, height; - - /* Repaint the damaged region onto the back buffer. */ - pixman_renderer_output_set_buffer(base, output->shadow_surface); - ec->renderer->repaint_output(base, damage); - - /* Transform and composite onto the frame buffer. */ - width = pixman_image_get_width(output->shadow_surface); - height = pixman_image_get_height(output->shadow_surface); - rects = pixman_region32_rectangles(damage, &nrects); - - for (i = 0; i < nrects; i++) { - switch (base->transform) { - default: - case WL_OUTPUT_TRANSFORM_NORMAL: - x1 = rects[i].x1; - x2 = rects[i].x2; - y1 = rects[i].y1; - y2 = rects[i].y2; - break; - case WL_OUTPUT_TRANSFORM_180: - x1 = width - rects[i].x2; - x2 = width - rects[i].x1; - y1 = height - rects[i].y2; - y2 = height - rects[i].y1; - break; - case WL_OUTPUT_TRANSFORM_90: - x1 = height - rects[i].y2; - x2 = height - rects[i].y1; - y1 = rects[i].x1; - y2 = rects[i].x2; - break; - case WL_OUTPUT_TRANSFORM_270: - x1 = rects[i].y1; - x2 = rects[i].y2; - y1 = width - rects[i].x2; - y2 = width - rects[i].x1; - break; + struct fbdev_compositor *compositor = to_fbdev_compositor(ec); + + if (compositor->use_pixman) + { + pixman_box32_t *rects; + int nrects, i, src_x, src_y, x1, y1, x2, y2, width, height; + /* Repaint the damaged region onto the back buffer. */ + pixman_renderer_output_set_buffer(base, output->shadow_surface); + ec->renderer->repaint_output(base, damage); + + /* Transform and composite onto the frame buffer. */ + width = pixman_image_get_width(output->shadow_surface); + height = pixman_image_get_height(output->shadow_surface); + rects = pixman_region32_rectangles(damage, &nrects); + + for (i = 0; i < nrects; i++) { + switch (base->transform) { + default: + case WL_OUTPUT_TRANSFORM_NORMAL: + x1 = rects[i].x1; + x2 = rects[i].x2; + y1 = rects[i].y1; + y2 = rects[i].y2; + break; + case WL_OUTPUT_TRANSFORM_180: + x1 = width - rects[i].x2; + x2 = width - rects[i].x1; + y1 = height - rects[i].y2; + y2 = height - rects[i].y1; + break; + case WL_OUTPUT_TRANSFORM_90: + x1 = height - rects[i].y2; + x2 = height - rects[i].y1; + y1 = rects[i].x1; + y2 = rects[i].x2; + break; + case WL_OUTPUT_TRANSFORM_270: + x1 = rects[i].y1; + x2 = rects[i].y2; + y1 = width - rects[i].x2; + y2 = width - rects[i].x1; + break; + } + src_x = x1; + src_y = y1; + + pixman_image_composite32(PIXMAN_OP_SRC, + output->shadow_surface, /* src */ + NULL /* mask */, + output->hw_surface, /* dest */ + src_x, src_y, /* src_x, src_y */ + 0, 0, /* mask_x, mask_y */ + x1, y1, /* dest_x, dest_y */ + x2 - x1, /* width */ + y2 - y1 /* height */); + /* Update the damage region. */ + pixman_region32_subtract(&ec->primary_plane.damage, + &ec->primary_plane.damage, damage); } - src_x = x1; - src_y = y1; - - pixman_image_composite32(PIXMAN_OP_SRC, - output->shadow_surface, /* src */ - NULL /* mask */, - output->hw_surface, /* dest */ - src_x, src_y, /* src_x, src_y */ - 0, 0, /* mask_x, mask_y */ - x1, y1, /* dest_x, dest_y */ - x2 - x1, /* width */ - y2 - y1 /* height */); } - - /* Update the damage region. */ - pixman_region32_subtract(&ec->primary_plane.damage, - &ec->primary_plane.damage, damage); + else + { + ec->renderer->repaint_output(base, damage); + } + /* Schedule the end of the frame. We do not sync this to the frame * buffer clock because users who want that should be using the DRM @@ -203,8 +216,9 @@ fbdev_output_repaint(struct weston_output *base, pixman_region32_t *damage) * * Finish the frame synchronised to the specified refresh rate. The * refresh rate is given in mHz and the interval in ms. */ - wl_event_source_timer_update(output->finish_frame_timer, - 1000000 / output->mode.refresh); + /*wl_event_source_timer_update(output->finish_frame_timer, + 1000000 / output->mode.refresh);*/ + wl_event_source_timer_update(output->finish_frame_timer, 1); } static int @@ -313,6 +327,38 @@ calculate_refresh_rate(struct fb_var_screeninfo *vinfo) } static int +fbdev_init_egl(struct fbdev_compositor *compositor, + struct fbdev_output *output) +{ + + static const EGLint config_attrs[] = { + EGL_SAMPLES, 0, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, EGL_DONT_CARE, + EGL_DEPTH_SIZE, 0, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE, + }; + + + EGLint visual_id = 0; + if (gl_renderer_create(&compositor->base, + compositor->display, config_attrs, + &visual_id) < 0) + return -1; + + if (gl_renderer_output_create(&output->base, + compositor->window) < 0) { + compositor->base.renderer->destroy(&compositor->base); + return -1; + } + return 0; +} + +static int fbdev_query_screen_info(struct fbdev_output *output, int fd, struct fbdev_screeninfo *info) { @@ -468,11 +514,14 @@ fbdev_frame_buffer_destroy(struct fbdev_output *output) { weston_log("Destroying fbdev frame buffer.\n"); - if (munmap(output->fb, output->fb_info.buffer_length) < 0) - weston_log("Failed to munmap frame buffer: %s\n", - strerror(errno)); + if(output->compositor->use_pixman) + { + if (munmap(output->fb, output->fb_info.buffer_length) < 0) + weston_log("Failed to munmap frame buffer: %s\n", + strerror(errno)); - output->fb = NULL; + output->fb = NULL; + } } static void fbdev_output_destroy(struct weston_output *base); @@ -506,9 +555,25 @@ fbdev_output_create(struct fbdev_compositor *compositor, goto out_free; } + if(compositor->use_pixman) + { if (fbdev_frame_buffer_map(output, fb_fd) < 0) { weston_log("Mapping frame buffer failed.\n"); goto out_free; + } + } + else + { + compositor->display = fbGetDisplay(compositor->base.wl_display); + if (compositor->display == NULL) { + fprintf(stderr, "failed to get display\n"); + return 0; + } + compositor->window = fbCreateWindow(compositor->display, -1, -1, 0, 0); + if (compositor->window == NULL) { + fprintf(stderr, "failed to create window\n"); + return 0; + } } output->base.start_repaint_loop = fbdev_output_start_repaint_loop; @@ -539,71 +604,73 @@ fbdev_output_create(struct fbdev_compositor *compositor, output->fb_info.height_mm, WL_OUTPUT_TRANSFORM_NORMAL); - width = output->fb_info.x_resolution; - height = output->fb_info.y_resolution; - - pixman_transform_init_identity(&transform); - switch (output->base.transform) { - default: - case WL_OUTPUT_TRANSFORM_NORMAL: - shadow_width = width; - shadow_height = height; - pixman_transform_rotate(&transform, - NULL, 0, 0); - pixman_transform_translate(&transform, NULL, - 0, 0); - break; - case WL_OUTPUT_TRANSFORM_180: - shadow_width = width; - shadow_height = height; - pixman_transform_rotate(&transform, - NULL, -pixman_fixed_1, 0); - pixman_transform_translate(NULL, &transform, - pixman_int_to_fixed(shadow_width), - pixman_int_to_fixed(shadow_height)); - break; - case WL_OUTPUT_TRANSFORM_270: - shadow_width = height; - shadow_height = width; - pixman_transform_rotate(&transform, - NULL, 0, pixman_fixed_1); - pixman_transform_translate(&transform, - NULL, - pixman_int_to_fixed(shadow_width), - 0); - break; - case WL_OUTPUT_TRANSFORM_90: - shadow_width = height; - shadow_height = width; - pixman_transform_rotate(&transform, - NULL, 0, -pixman_fixed_1); - pixman_transform_translate(&transform, - NULL, - 0, - pixman_int_to_fixed(shadow_height)); - break; - } - - bytes_per_pixel = output->fb_info.bits_per_pixel / 8; + if(compositor->use_pixman) + { + width = output->fb_info.x_resolution; + height = output->fb_info.y_resolution; - output->shadow_buf = malloc(width * height * bytes_per_pixel); - output->shadow_surface = - pixman_image_create_bits(output->fb_info.pixel_format, - shadow_width, shadow_height, - output->shadow_buf, - shadow_width * bytes_per_pixel); - if (output->shadow_buf == NULL || output->shadow_surface == NULL) { - weston_log("Failed to create surface for frame buffer.\n"); - goto out_hw_surface; - } + pixman_transform_init_identity(&transform); + switch (output->base.transform) { + default: + case WL_OUTPUT_TRANSFORM_NORMAL: + shadow_width = width; + shadow_height = height; + pixman_transform_rotate(&transform, + NULL, 0, 0); + pixman_transform_translate(&transform, NULL, + 0, 0); + break; + case WL_OUTPUT_TRANSFORM_180: + shadow_width = width; + shadow_height = height; + pixman_transform_rotate(&transform, + NULL, -pixman_fixed_1, 0); + pixman_transform_translate(NULL, &transform, + pixman_int_to_fixed(shadow_width), + pixman_int_to_fixed(shadow_height)); + break; + case WL_OUTPUT_TRANSFORM_270: + shadow_width = height; + shadow_height = width; + pixman_transform_rotate(&transform, + NULL, 0, pixman_fixed_1); + pixman_transform_translate(&transform, + NULL, + pixman_int_to_fixed(shadow_width), + 0); + break; + case WL_OUTPUT_TRANSFORM_90: + shadow_width = height; + shadow_height = width; + pixman_transform_rotate(&transform, + NULL, 0, -pixman_fixed_1); + pixman_transform_translate(&transform, + NULL, + 0, + pixman_int_to_fixed(shadow_height)); + break; + } - /* No need in transform for normal output */ - if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL) - pixman_image_set_transform(output->shadow_surface, &transform); + bytes_per_pixel = output->fb_info.bits_per_pixel / 8; + + output->shadow_buf = malloc(width * height * bytes_per_pixel); + output->shadow_surface = + pixman_image_create_bits(output->fb_info.pixel_format, + shadow_width, shadow_height, + output->shadow_buf, + shadow_width * bytes_per_pixel); + if (output->shadow_buf == NULL || output->shadow_surface == NULL) { + weston_log("Failed to create surface for frame buffer.\n"); + goto out_hw_surface; + } - if (pixman_renderer_output_create(&output->base) < 0) - goto out_shadow_surface; + /* No need in transform for normal output */ + if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL) + pixman_image_set_transform(output->shadow_surface, &transform); + if (pixman_renderer_output_create(&output->base) < 0) + goto out_shadow_surface; + } loop = wl_display_get_event_loop(compositor->base.wl_display); output->finish_frame_timer = wl_event_loop_add_timer(loop, finish_frame_handler, output); @@ -615,15 +682,25 @@ fbdev_output_create(struct fbdev_compositor *compositor, weston_log_continue(STAMP_SPACE "guessing %d Hz and 96 dpi\n", output->mode.refresh / 1000); + printf("compositor->use_pixman=%d\n",compositor->use_pixman); + if(!compositor->use_pixman) + { + if (fbdev_init_egl(compositor, output) < 0) + goto out_hw_surface; + } return 0; out_shadow_surface: pixman_image_unref(output->shadow_surface); output->shadow_surface = NULL; out_hw_surface: - free(output->shadow_buf); - pixman_image_unref(output->hw_surface); - output->hw_surface = NULL; + + if(compositor->use_pixman) + { + free(output->shadow_buf); + pixman_image_unref(output->hw_surface); + output->hw_surface = NULL; + } weston_output_destroy(&output->base); fbdev_frame_buffer_destroy(output); out_free: @@ -636,24 +713,36 @@ static void fbdev_output_destroy(struct weston_output *base) { struct fbdev_output *output = to_fbdev_output(base); + struct fbdev_compositor *compositor = to_fbdev_compositor(output->base.compositor); weston_log("Destroying fbdev output.\n"); /* Close the frame buffer. */ fbdev_output_disable(base); + if(compositor->use_pixman) + { - if (base->renderer_state != NULL) - pixman_renderer_output_destroy(base); - if (output->shadow_surface != NULL) { - pixman_image_unref(output->shadow_surface); - output->shadow_surface = NULL; - } + if (base->renderer_state != NULL) + pixman_renderer_output_destroy(base); - if (output->shadow_buf != NULL) { - free(output->shadow_buf); - output->shadow_buf = NULL; + if (output->shadow_surface != NULL) { + pixman_image_unref(output->shadow_surface); + output->shadow_surface = NULL; + } + + if (output->shadow_buf != NULL) { + free(output->shadow_buf); + output->shadow_buf = NULL; + } } + else + { + fbDestroyDisplay(compositor->display); + fbDestroyWindow(compositor->window); + + gl_renderer_output_destroy(base); + } /* Remove the output. */ wl_list_remove(&output->base.link); @@ -834,7 +923,9 @@ switch_vt_binding(struct wl_seat *seat, uint32_t time, uint32_t key, void *data) } static struct weston_compositor * -fbdev_compositor_create(struct wl_display *display, int *argc, char *argv[], +fbdev_compositor_create(struct wl_display *display, + int use_pixman, + int argc, char *argv[], const char *config_file, struct fbdev_parameters *param) { struct fbdev_compositor *compositor; @@ -863,6 +954,10 @@ fbdev_compositor_create(struct wl_display *display, int *argc, char *argv[], weston_log("Failed to initialize tty.\n"); goto out_udev; } + weston_log("Using %s renderer\n", use_pixman ? "pixman" : "gl"); + printf("use_pixman=%d \n", use_pixman); + compositor->use_pixman = use_pixman; + compositor->base.destroy = fbdev_compositor_destroy; compositor->base.restore = fbdev_restore; @@ -875,9 +970,10 @@ fbdev_compositor_create(struct wl_display *display, int *argc, char *argv[], MODIFIER_CTRL | MODIFIER_ALT, switch_vt_binding, compositor); - - if (pixman_renderer_init(&compositor->base) < 0) - goto out_tty; + if (compositor->use_pixman) { + if (pixman_renderer_init(&compositor->base) < 0) + goto out_tty; + } if (fbdev_output_create(compositor, param->device) < 0) goto out_pixman; @@ -908,6 +1004,7 @@ WL_EXPORT struct weston_compositor * backend_init(struct wl_display *display, int *argc, char *argv[], const char *config_file) { + int use_pixman = 0; /* TODO: Ideally, available frame buffers should be enumerated using * udev, rather than passing a device node in as a parameter. */ struct fbdev_parameters param = { @@ -918,10 +1015,11 @@ backend_init(struct wl_display *display, int *argc, char *argv[], const struct weston_option fbdev_options[] = { { WESTON_OPTION_INTEGER, "tty", 0, ¶m.tty }, { WESTON_OPTION_STRING, "device", 0, ¶m.device }, + { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &use_pixman }, }; parse_options(fbdev_options, ARRAY_LENGTH(fbdev_options), argc, argv); - return fbdev_compositor_create(display, argc, argv, config_file, + return fbdev_compositor_create(display, use_pixman, argc, argv, config_file, ¶m); } -- 1.8.3.2