diff options
author | Pavlo Suikov <pavlo.suikov@ti.com> | 2012-11-29 19:30:01 +0200 |
---|---|---|
committer | Daniel Levin <dendy@ti.com> | 2012-12-04 15:42:16 +0200 |
commit | d3095e42069bb1964c34f72ae39bc33b6bd35c10 (patch) | |
tree | 90f0d2c17f25baed33413980599913b1c087dd51 | |
parent | b5434c2ebc47f25246b211f0a86bab1faf097cb2 (diff) | |
parent | c0ed577b7355d11497d164488241deafb1a9dcb6 (diff) | |
download | hardware_ti_omap4-d3095e42069bb1964c34f72ae39bc33b6bd35c10.zip hardware_ti_omap4-d3095e42069bb1964c34f72ae39bc33b6bd35c10.tar.gz hardware_ti_omap4-d3095e42069bb1964c34f72ae39bc33b6bd35c10.tar.bz2 |
Merge remote-tracking branch 'gl-mirror/d-jb-mr0-release-hwc' into d-jb-mr1-release
Early regionizer adaptation for HWC API 1.0.
Change-Id: I1842e09500af8c9b79c0a01bb960ab9f2427d488
Signed-off-by: Pavlo Suikov <pavlo.suikov@ti.com>
-rw-r--r-- | hwc/Android.mk | 7 | ||||
-rw-r--r-- | hwc/dock_image.c | 196 | ||||
-rw-r--r-- | hwc/dock_image.h | 38 | ||||
-rw-r--r-- | hwc/hwc.c | 914 | ||||
-rw-r--r-- | hwc/hwc_dev.h | 172 | ||||
-rw-r--r-- | hwc/rgz_2d.c | 1017 | ||||
-rw-r--r-- | hwc/rgz_2d.h | 32 | ||||
-rw-r--r-- | hwc/sw_vsync.c | 145 | ||||
-rw-r--r-- | hwc/sw_vsync.h | 25 | ||||
-rw-r--r-- | include/gralloc/ti_handle_wrapper.h | 85 |
10 files changed, 1680 insertions, 951 deletions
diff --git a/hwc/Android.mk b/hwc/Android.mk index 60b421d..dd83714 100644 --- a/hwc/Android.mk +++ b/hwc/Android.mk @@ -7,8 +7,8 @@ LOCAL_PRELINK_MODULE := false LOCAL_ARM_MODE := arm LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/../vendor/lib/hw LOCAL_SHARED_LIBRARIES := liblog libEGL libcutils libutils libhardware libhardware_legacy libz \ - libion -LOCAL_SRC_FILES := hwc.c rgz_2d.c + libion_ti +LOCAL_SRC_FILES := hwc.c rgz_2d.c dock_image.c sw_vsync.c LOCAL_STATIC_LIBRARIES := libpng LOCAL_MODULE_TAGS := optional @@ -18,7 +18,8 @@ LOCAL_CFLAGS := -DLOG_TAG=\"ti_hwc\" LOCAL_C_INCLUDES += external/libpng external/zlib LOCAL_C_INCLUDES += \ - $(LOCAL_PATH)/../edid/inc + $(LOCAL_PATH)/../edid/inc \ + $(LOCAL_PATH)/../include LOCAL_SHARED_LIBRARIES += libedid # LOG_NDEBUG=0 means verbose logging enabled diff --git a/hwc/dock_image.c b/hwc/dock_image.c new file mode 100644 index 0000000..b74a17e --- /dev/null +++ b/hwc/dock_image.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) Texas Instruments - http://www.ti.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <errno.h> +#include <stdint.h> +#include <stdbool.h> +#include <sys/ioctl.h> +#include <sys/mman.h> + +#include <cutils/log.h> +#include <cutils/properties.h> +#include <png.h> + +#include <linux/fb.h> + +#include "hwc_dev.h" +#include "dock_image.h" + +static struct dock_image_state { + void *buffer; /* start of fb for hdmi */ + uint32_t buffer_size; /* size of fb for hdmi */ + + uint32_t max_width; + uint32_t max_height; + + image_info_t image; +} dock_image; + +static void free_png_image(image_info_t *img) +{ + memset(img, 0, sizeof(*img)); +} + +static int load_png_image(char *path, image_info_t *img) +{ + void *ptr = NULL; + png_bytepp row_pointers = NULL; + + FILE *fd = fopen(path, "rb"); + if (!fd) { + ALOGE("failed to open PNG file %s: (%d)", path, errno); + return -EINVAL; + } + + const int SIZE_PNG_HEADER = 8; + uint8_t header[SIZE_PNG_HEADER]; + fread(header, 1, SIZE_PNG_HEADER, fd); + if (png_sig_cmp(header, 0, SIZE_PNG_HEADER)) { + ALOGE("%s is not a PNG file", path); + goto fail; + } + + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + goto fail_alloc; + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + goto fail_alloc; + + if (setjmp(png_jmpbuf(png_ptr))) + goto fail_alloc; + + png_init_io(png_ptr, fd); + png_set_sig_bytes(png_ptr, SIZE_PNG_HEADER); + png_set_user_limits(png_ptr, dock_image.max_width, dock_image.max_height); + png_read_info(png_ptr, info_ptr); + + uint8_t bit_depth = png_get_bit_depth(png_ptr, info_ptr); + uint32_t width = png_get_image_width(png_ptr, info_ptr); + uint32_t height = png_get_image_height(png_ptr, info_ptr); + uint8_t color_type = png_get_color_type(png_ptr, info_ptr); + + switch (color_type) { + case PNG_COLOR_TYPE_PALETTE: + png_set_palette_to_rgb(png_ptr); + png_set_filler(png_ptr, 128, PNG_FILLER_AFTER); + break; + case PNG_COLOR_TYPE_GRAY: + if (bit_depth < 8) { + png_set_expand_gray_1_2_4_to_8(png_ptr); + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png_ptr); + } else { + png_set_filler(png_ptr, 128, PNG_FILLER_AFTER); + } + /* fall through */ + case PNG_COLOR_TYPE_GRAY_ALPHA: + png_set_gray_to_rgb(png_ptr); + break; + case PNG_COLOR_TYPE_RGB: + png_set_filler(png_ptr, 128, PNG_FILLER_AFTER); + /* fall through */ + case PNG_COLOR_TYPE_RGB_ALPHA: + png_set_bgr(png_ptr); + break; + default: + ALOGE("unsupported PNG color: %x", color_type); + goto fail_alloc; + } + + if (bit_depth == 16) + png_set_strip_16(png_ptr); + + const uint32_t bpp = 4; + img->size = ALIGN(width * height * bpp, 4096); + if ((uint32_t)img->size > dock_image.buffer_size) { + ALOGE("image does not fit into framebuffer area (%d > %d)", img->size, dock_image.buffer_size); + goto fail_alloc; + } + img->ptr = dock_image.buffer; + + row_pointers = calloc(height, sizeof(*row_pointers)); + if (!row_pointers) { + ALOGE("failed to allocate row pointers"); + goto fail_alloc; + } + uint32_t i; + for (i = 0; i < height; i++) + row_pointers[i] = img->ptr + i * width * bpp; + png_set_rows(png_ptr, info_ptr, row_pointers); + png_read_update_info(png_ptr, info_ptr); + img->rowbytes = png_get_rowbytes(png_ptr, info_ptr); + + png_read_image(png_ptr, row_pointers); + png_read_end(png_ptr, NULL); + free(row_pointers); + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(fd); + img->width = width; + img->height = height; + return 0; + +fail_alloc: + free_png_image(img); + free(row_pointers); + if (!png_ptr || !info_ptr) + ALOGE("failed to allocate PNG structures"); + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); +fail: + fclose(fd); + return -EINVAL; +} + +int init_dock_image(omap_hwc_device_t *hwc_dev, uint32_t max_width, uint32_t max_height) +{ + int err = 0; + + struct fb_fix_screeninfo fix; + if (ioctl(hwc_dev->fb_fd, FBIOGET_FSCREENINFO, &fix)) { + ALOGE("failed to get fb info (%d)", errno); + err = -errno; + goto done; + } + + dock_image.buffer_size = fix.smem_len; + dock_image.buffer = mmap(NULL, fix.smem_len, PROT_WRITE, MAP_SHARED, hwc_dev->fb_fd, 0); + if (dock_image.buffer == MAP_FAILED) { + ALOGE("failed to map fb memory"); + err = -errno; + goto done; + } + + dock_image.max_width = max_width; + dock_image.max_height = max_height; + + done: + return err; +} + +void load_dock_image() +{ + if (!dock_image.image.rowbytes) { + char value[PROPERTY_VALUE_MAX]; + property_get("persist.hwc.dock_image", value, "/vendor/res/images/dock/dock.png"); + load_png_image(value, &dock_image.image); + } +} + +image_info_t *get_dock_image() +{ + return &dock_image.image; +} + diff --git a/hwc/dock_image.h b/hwc/dock_image.h new file mode 100644 index 0000000..44a3271 --- /dev/null +++ b/hwc/dock_image.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) Texas Instruments - http://www.ti.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DOCK_IMAGE__ +#define __DOCK_IMAGE__ + +#include <stdint.h> + +/* ARGB image */ +struct image_info { + int width; + int height; + int rowbytes; + int size; + uint8_t *ptr; +}; +typedef struct image_info image_info_t; + +typedef struct omap_hwc_device omap_hwc_device_t; + +int init_dock_image(omap_hwc_device_t *hwc_dev, uint32_t max_width, uint32_t max_height); +void load_dock_image(); +image_info_t *get_dock_image(); + +#endif @@ -18,14 +18,11 @@ #include <malloc.h> #include <stdlib.h> #include <stdarg.h> +#include <stdbool.h> #include <fcntl.h> #include <poll.h> #include <sys/ioctl.h> -#include <linux/fb.h> -#include <linux/omapfb.h> -#include <sys/mman.h> #include <sys/resource.h> -#include <stdbool.h> #include <cutils/properties.h> #include <cutils/log.h> @@ -33,20 +30,20 @@ #define HWC_REMOVE_DEPRECATED_VERSIONS 1 #include <hardware/hardware.h> #include <hardware/hwcomposer.h> -#include <EGL/egl.h> #include <hardware_legacy/uevent.h> -#include <png.h> -#include <utils/Timers.h> - #include <system/graphics.h> #include <ui/S3DFormat.h> +#include <utils/Timers.h> +#include <EGL/egl.h> #include <edid_parser.h> -#include <linux/bltsville.h> - -#define MAX_HWC_LAYERS 32 +#include <linux/fb.h> +#include <linux/omapfb.h> +#include <ion_ti/ion.h> -#define ASPECT_RATIO_TOLERANCE 0.02f +#include "hwc_dev.h" +#include "dock_image.h" +#include "sw_vsync.h" #define min(a, b) ( { typeof(a) __a = (a), __b = (b); __a < __b ? __a : __b; } ) #define max(a, b) ( { typeof(a) __a = (a), __b = (b); __a > __b ? __a : __b; } ) @@ -57,61 +54,11 @@ #define DIV_ROUND_UP(a, b) (((a) + (b) - 1) / (b)) -#include <video/dsscomp.h> -#include <video/omap_hwc.h> - -#include "hal_public.h" -#include "rgz_2d.h" - -#include <linux/ion.h> -#include <linux/omap_ion.h> -#include <ion/ion.h> - +#define MAX_HWC_LAYERS 32 #define MAX_HW_OVERLAYS 4 #define NUM_NONSCALING_OVERLAYS 1 #define NUM_EXT_DISPLAY_BACK_BUFFERS 2 - -struct ext_transform_t { - __u8 rotation : 3; /* 90-degree clockwise rotations */ - __u8 hflip : 1; /* flip l-r (after rotation) */ - __u8 enabled : 1; /* cloning enabled */ - __u8 docking : 1; /* docking vs. mirroring - used for state */ -}; - -/* cloning support and state */ -struct omap4_hwc_ext { - /* support */ - struct ext_transform_t mirror; /* mirroring settings */ - struct ext_transform_t dock; /* docking settings */ - float lcd_xpy; /* pixel ratio for UI */ - __u8 avoid_mode_change; /* use HDMI mode used for mirroring if possible */ - __u8 force_dock; /* must dock */ - __u8 hdmi_state; /* whether HDMI is connected */ - - /* state */ - __u8 on_tv; /* using a tv */ - struct ext_transform_t current; /* current settings */ - struct ext_transform_t last; /* last-used settings */ - - /* configuration */ - __u32 last_xres_used; /* resolution and pixel ratio used for mode selection */ - __u32 last_yres_used; - __u32 last_mode; /* 2-s complement of last HDMI mode set, 0 if none */ - __u32 mirror_mode; /* 2-s complement of mode used when mirroring */ - float last_xpy; - __u16 width; /* external screen dimensions */ - __u16 height; - __u32 xres; /* external screen resolution */ - __u32 yres; - float m[2][3]; /* external transformation matrix */ - hwc_rect_t mirror_region; /* region of screen to mirror */ - - bool s3d_enabled; - bool s3d_capable; - enum S3DLayoutType s3d_type; - enum S3DLayoutOrder s3d_order; -}; -typedef struct omap4_hwc_ext omap4_hwc_ext_t; +#define ASPECT_RATIO_TOLERANCE 0.02f /* used by property settings */ enum { @@ -119,107 +66,6 @@ enum { EXT_HFLIP = (1 << 2), /* flip l-r on output (after rotation) */ }; -enum bltpolicy { - BLTPOLICY_DISABLED = 0, - BLTPOLICY_DEFAULT = 1, /* Default blit policy */ - BLTPOLICY_ALL, /* Test mode to attempt to blit all */ -}; - -enum bltmode { - BLTMODE_PAINT = 0, /* Attempt to blit layer by layer */ - BLTMODE_REGION = 1, /* Attempt to blit layers via regions */ -}; - -/* ARGB image */ -struct omap4_hwc_img { - int width; - int height; - int rowbytes; - int size; - unsigned char *ptr; -} dock_image = { .rowbytes = 0 }; - -struct omap4_hwc_module { - hwc_module_t base; - - IMG_framebuffer_device_public_t *fb_dev; -}; -typedef struct omap4_hwc_module omap4_hwc_module_t; - -struct counts { - unsigned int possible_overlay_layers; - unsigned int composited_layers; - unsigned int scaled_layers; - unsigned int RGB; - unsigned int BGR; - unsigned int NV12; - unsigned int dockable; - unsigned int protected; - - unsigned int max_hw_overlays; - unsigned int max_scaling_overlays; - unsigned int mem; - unsigned int s3d; -}; - -struct omap4_hwc_device { - /* static data */ - hwc_composer_device_1_t base; - hwc_procs_t *procs; - pthread_t hdmi_thread; - pthread_mutex_t lock; - - IMG_framebuffer_device_public_t *fb_dev; - struct dsscomp_display_info fb_dis; - int fb_fd; /* file descriptor for /dev/fb0 */ - int dsscomp_fd; /* file descriptor for /dev/dsscomp */ - int hdmi_fb_fd; /* file descriptor for /dev/fb1 */ - int pipe_fds[2]; /* pipe to event thread */ - - int img_mem_size; /* size of fb for hdmi */ - void *img_mem_ptr; /* start of fb for hdmi */ - - int flags_rgb_order; - int flags_nv12_only; - float upscaled_nv12_limit; - - int on_tv; /* using a tv */ - int force_sgx; - omap4_hwc_ext_t ext; /* external mirroring data */ - int idle; - - float primary_m[2][3]; /* internal transformation matrix */ - int primary_transform; - int primary_rotation; - hwc_rect_t primary_region; - - buffer_handle_t *buffers; - int use_sgx; - int swap_rb; - unsigned int post2_layers; /* Buffers used with DSS pipes*/ - unsigned int post2_blit_buffers; /* Buffers used with blit */ - int ext_ovls; /* # of overlays on external display for current composition */ - int ext_ovls_wanted; /* # of overlays that should be on external display for current composition */ - int last_ext_ovls; /* # of overlays on external/internal display for last composition */ - int last_int_ovls; - - enum S3DLayoutType s3d_input_type; - enum S3DLayoutOrder s3d_input_order; - - enum bltmode blt_mode; - enum bltpolicy blt_policy; - - int blit_flags; - int blit_num; - struct omap_hwc_data comp_data; /* This is a kernel data structure */ - struct rgz_blt_entry blit_ops[RGZ_MAX_BLITS]; - struct counts stats; - int ion_fd; - struct ion_handle *ion_handles[2]; - -}; -typedef struct omap4_hwc_device omap4_hwc_device_t; - #define HAL_FMT(f) ((f) == HAL_PIXEL_FORMAT_TI_NV12 ? "NV12" : \ (f) == HAL_PIXEL_FORMAT_TI_NV12_1D ? "NV12" : \ (f) == HAL_PIXEL_FORMAT_YV12 ? "YV12" : \ @@ -234,10 +80,11 @@ typedef struct omap4_hwc_device omap4_hwc_device_t; (f) == OMAP_DSS_COLOR_ARGB32 ? "ARGB32" : \ (f) == OMAP_DSS_COLOR_RGB16 ? "RGB565" : "??") -static int debug = 0; -static int debugpost2 = 0; -static int debugblt = 0; +static bool debug = false; +static bool debugpost2 = false; +static bool debugblt = false; static rgz_t grgz; +static rgz_ext_layer_list_t grgz_ext_layer_list; static struct bvsurfgeom gscrngeom; static void showfps(void) @@ -280,7 +127,7 @@ static void dump_layer(hwc_layer_1_t const* l) static void dump_dsscomp(struct dsscomp_setup_dispc_data *d) { - unsigned i; + uint32_t i; ALOGD("[%08x] set: %c%c%c %d ovls\n", d->sync_id, @@ -331,7 +178,7 @@ static void dump_printf(struct dump_buf *buf, const char *fmt, ...) va_end(ap); } -static void dump_set_info(omap4_hwc_device_t *hwc_dev, hwc_display_contents_1_t* list) +static void dump_set_info(omap_hwc_device_t *hwc_dev, hwc_display_contents_1_t* list) { struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data; char logbuf[1024]; @@ -339,7 +186,7 @@ static void dump_set_info(omap4_hwc_device_t *hwc_dev, hwc_display_contents_1_t* .buf = logbuf, .buf_len = sizeof(logbuf), }; - unsigned int i; + uint32_t i; dump_printf(&log, "set H{"); for (i = 0; list && i < list->numHwLayers; i++) { @@ -399,7 +246,7 @@ static void dump_set_info(omap4_hwc_device_t *hwc_dev, hwc_display_contents_1_t* static int sync_id = 0; -static int omap4_hwc_is_valid_format(int format) +static bool is_valid_format(uint32_t format) { switch(format) { case HAL_PIXEL_FORMAT_RGB_565: @@ -409,25 +256,25 @@ static int omap4_hwc_is_valid_format(int format) case HAL_PIXEL_FORMAT_BGRX_8888: case HAL_PIXEL_FORMAT_TI_NV12: case HAL_PIXEL_FORMAT_TI_NV12_1D: - return 1; + return true; default: - return 0; + return false; } } -static __u32 get_s3d_layout_type(hwc_layer_1_t *layer) +static uint32_t get_s3d_layout_type(hwc_layer_1_t *layer) { return (layer->flags & S3DLayoutTypeMask) >> S3DLayoutTypeShift; } -static __u32 get_s3d_layout_order(hwc_layer_1_t *layer) +static uint32_t get_s3d_layout_order(hwc_layer_1_t *layer) { return (layer->flags & S3DLayoutOrderMask) >> S3DLayoutOrderShift; } -static int scaled(hwc_layer_1_t *layer) +static bool scaled(hwc_layer_1_t *layer) { int w = WIDTH(layer->sourceCrop); int h = HEIGHT(layer->sourceCrop); @@ -440,31 +287,30 @@ static int scaled(hwc_layer_1_t *layer) || get_s3d_layout_type(layer) != eMono; } -static int is_protected(hwc_layer_1_t *layer) +static bool is_protected(hwc_layer_1_t *layer) { IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; - return (handle->usage & GRALLOC_USAGE_PROTECTED); + return (handle->usage & GRALLOC_USAGE_PROTECTED) != 0; } #define is_BLENDED(layer) ((layer)->blending != HWC_BLENDING_NONE) -static int is_RGB(IMG_native_handle_t *handle) +static bool is_RGB(IMG_native_handle_t *handle) { switch(handle->iFormat) { case HAL_PIXEL_FORMAT_BGRA_8888: case HAL_PIXEL_FORMAT_BGRX_8888: case HAL_PIXEL_FORMAT_RGB_565: - return 1; + return true; default: - return 0; + return false; } } -static int get_rgb_bpp(IMG_native_handle_t *handle) +static uint32_t get_format_bpp(uint32_t format) { - switch(handle->iFormat) - { + switch(format) { case HAL_PIXEL_FORMAT_BGRA_8888: case HAL_PIXEL_FORMAT_BGRX_8888: case HAL_PIXEL_FORMAT_RGBX_8888: @@ -472,47 +318,50 @@ static int get_rgb_bpp(IMG_native_handle_t *handle) return 32; case HAL_PIXEL_FORMAT_RGB_565: return 16; + case HAL_PIXEL_FORMAT_TI_NV12: + case HAL_PIXEL_FORMAT_TI_NV12_1D: + return 8; default: return 0; } } -static int is_BGR_format(int format) +static bool is_BGR_format(uint32_t format) { switch (format) { case HAL_PIXEL_FORMAT_RGBX_8888: case HAL_PIXEL_FORMAT_RGBA_8888: - return 1; + return true; default: - return 0; + return false; } } -static int is_BGR(IMG_native_handle_t *handle) +static bool is_BGR(IMG_native_handle_t *handle) { return is_BGR_format(handle->iFormat); } -static int is_NV12(IMG_native_handle_t *handle) +static bool is_NV12(IMG_native_handle_t *handle) { switch(handle->iFormat) { case HAL_PIXEL_FORMAT_TI_NV12: case HAL_PIXEL_FORMAT_TI_NV12_1D: - return 1; + return true; default: - return 0; + return false; } } -static int is_upscaled_NV12(omap4_hwc_device_t *hwc_dev, hwc_layer_1_t *layer) +static bool is_upscaled_NV12(omap_hwc_device_t *hwc_dev, hwc_layer_1_t *layer) { if (!layer) - return 0; + return false; IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; if (!is_NV12(handle)) - return 0; + return false; int w = WIDTH(layer->sourceCrop); int h = HEIGHT(layer->sourceCrop); @@ -524,14 +373,14 @@ static int is_upscaled_NV12(omap4_hwc_device_t *hwc_dev, hwc_layer_1_t *layer) HEIGHT(layer->displayFrame) >= h * hwc_dev->upscaled_nv12_limit); } -static int dockable(hwc_layer_1_t *layer) +static bool dockable(hwc_layer_1_t *layer) { IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; - return (handle->usage & GRALLOC_USAGE_EXTERNAL_DISP); + return (handle->usage & GRALLOC_USAGE_EXTERNAL_DISP) != 0; } -static unsigned int mem1d(IMG_native_handle_t *handle) +static uint32_t mem1d(IMG_native_handle_t *handle) { if (handle == NULL || is_NV12(handle)) return 0; @@ -541,11 +390,9 @@ static unsigned int mem1d(IMG_native_handle_t *handle) return stride * handle->iHeight; } -static void -omap4_hwc_setup_layer_base(struct dss2_ovl_cfg *oc, int index, int format, int blended, int width, int height) +static void setup_layer_base(struct dss2_ovl_cfg *oc, int index, uint32_t format, + bool blended, int width, int height) { - unsigned int bits_per_pixel; - /* YUV2RGB conversion */ const struct omap_dss_cconv_coefs ctbl_bt601_5 = { 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, @@ -556,25 +403,21 @@ omap4_hwc_setup_layer_base(struct dss2_ovl_cfg *oc, int index, int format, int b case HAL_PIXEL_FORMAT_RGBA_8888: case HAL_PIXEL_FORMAT_BGRA_8888: oc->color_mode = OMAP_DSS_COLOR_ARGB32; - bits_per_pixel = 32; if (blended) break; case HAL_PIXEL_FORMAT_RGBX_8888: case HAL_PIXEL_FORMAT_BGRX_8888: oc->color_mode = OMAP_DSS_COLOR_RGB24U; - bits_per_pixel = 32; break; case HAL_PIXEL_FORMAT_RGB_565: oc->color_mode = OMAP_DSS_COLOR_RGB16; - bits_per_pixel = 16; break; case HAL_PIXEL_FORMAT_TI_NV12: case HAL_PIXEL_FORMAT_TI_NV12_1D: oc->color_mode = OMAP_DSS_COLOR_NV12; - bits_per_pixel = 8; oc->cconv = ctbl_bt601_5; break; @@ -586,7 +429,7 @@ omap4_hwc_setup_layer_base(struct dss2_ovl_cfg *oc, int index, int format, int b oc->width = width; oc->height = height; - oc->stride = ALIGN(width, HW_ALIGN) * bits_per_pixel / 8; + oc->stride = ALIGN(width, HW_ALIGN) * get_format_bpp(format) / 8; oc->enabled = 1; oc->global_alpha = 255; @@ -602,16 +445,14 @@ omap4_hwc_setup_layer_base(struct dss2_ovl_cfg *oc, int index, int format, int b oc->vc1.enable = 0; } -static void -omap4_hwc_setup_layer(omap4_hwc_device_t *hwc_dev, struct dss2_ovl_info *ovl, - hwc_layer_1_t *layer, int index, - int format, int width, int height) +static void setup_layer(omap_hwc_device_t *hwc_dev, struct dss2_ovl_info *ovl, + hwc_layer_1_t *layer, int index, uint32_t format, int width, int height) { struct dss2_ovl_cfg *oc = &ovl->cfg; //dump_layer(layer); - omap4_hwc_setup_layer_base(oc, index, format, is_BLENDED(layer), width, height); + setup_layer_base(oc, index, format, is_BLENDED(layer), width, height); /* convert transformation - assuming 0-set config */ if (layer->transform & HWC_TRANSFORM_FLIP_H) @@ -642,7 +483,7 @@ omap4_hwc_setup_layer(omap4_hwc_device_t *hwc_dev, struct dss2_ovl_info *ovl, const float m_unit[2][3] = { { 1., 0., 0. }, { 0., 1., 0. } }; -static inline void m_translate(float m[2][3], int dx, int dy) +static inline void m_translate(float m[2][3], float dx, float dy) { m[0][2] += dx; m[1][2] += dy; @@ -666,7 +507,7 @@ static void m_rotate(float m[2][3], int quarter_turns) if (quarter_turns & 2) m_scale(m, 1, -1, 1, -1); if (quarter_turns & 1) { - int q; + float q; q = m[0][0]; m[0][0] = -m[1][0]; m[1][0] = q; q = m[0][1]; m[0][1] = -m[1][1]; m[1][1] = q; q = m[0][2]; m[0][2] = -m[1][2]; m[1][2] = q; @@ -684,11 +525,11 @@ static inline int m_round(float x) * and height for a screen of xres/yres and physical size of width/height. * The adjusted size is the largest that fits into the screen. */ -static void get_max_dimensions(__u32 orig_xres, __u32 orig_yres, +static void get_max_dimensions(uint32_t orig_xres, uint32_t orig_yres, float xpy, - __u32 scr_xres, __u32 scr_yres, - __u32 scr_width, __u32 scr_height, - __u32 *adj_xres, __u32 *adj_yres) + uint32_t scr_xres, uint32_t scr_yres, + uint32_t scr_width, uint32_t scr_height, + uint32_t *adj_xres, uint32_t *adj_yres) { /* assume full screen (largest size)*/ *adj_xres = scr_xres; @@ -706,12 +547,12 @@ static void get_max_dimensions(__u32 orig_xres, __u32 orig_yres, /* allow for tolerance so we avoid scaling if framebuffer is standard size */ if (x_factor < y_factor * (1.f - ASPECT_RATIO_TOLERANCE)) - *adj_xres = (__u32) (x_factor * *adj_xres / y_factor + 0.5); + *adj_xres = (uint32_t) (x_factor * *adj_xres / y_factor + 0.5); else if (x_factor * (1.f - ASPECT_RATIO_TOLERANCE) > y_factor) - *adj_yres = (__u32) (y_factor * *adj_yres / x_factor + 0.5); + *adj_yres = (uint32_t) (y_factor * *adj_yres / x_factor + 0.5); } -static void set_ext_matrix(omap4_hwc_ext_t *ext, struct hwc_rect region) +static void set_ext_matrix(omap_hwc_ext_t *ext, struct hwc_rect region) { int orig_w = WIDTH(region); int orig_h = HEIGHT(region); @@ -721,7 +562,7 @@ static void set_ext_matrix(omap4_hwc_ext_t *ext, struct hwc_rect region) m = (center-from-target-center) * (scale-to-target) * (mirror) * (rotate) * (center-to-original-center) */ memcpy(ext->m, m_unit, sizeof(m_unit)); - m_translate(ext->m, -(orig_w >> 1) - region.left, -(orig_h >> 1) - region.top); + m_translate(ext->m, -(orig_w / 2.0f) - region.left, -(orig_h / 2.0f) - region.top); m_rotate(ext->m, ext->current.rotation); if (ext->current.hflip) m_scale(ext->m, 1, -1, 1, 1); @@ -732,7 +573,7 @@ static void set_ext_matrix(omap4_hwc_ext_t *ext, struct hwc_rect region) } /* get target size */ - __u32 adj_xres, adj_yres; + uint32_t adj_xres, adj_yres; get_max_dimensions(orig_w, orig_h, xpy, ext->xres, ext->yres, ext->width, ext->height, &adj_xres, &adj_yres); @@ -759,7 +600,8 @@ crop_to_rect(struct dss2_ovl_cfg *cfg, struct hwc_rect vis_rect) vis.lt[0] = vis_rect.left; vis.lt[1] = vis_rect.top; vis.rb[0] = vis_rect.right; vis.rb[1] = vis_rect.bottom; - int c, swap = cfg->rotation & 1; + int c; + bool swap = cfg->rotation & 1; /* align crop window with display coordinates */ if (swap) @@ -813,8 +655,7 @@ crop_to_rect(struct dss2_ovl_cfg *cfg, struct hwc_rect vis_rect) return 0; } -static void -omap4_hwc_apply_transform(float transform[2][3],struct dss2_ovl_cfg *oc) +static void apply_transform(float transform[2][3],struct dss2_ovl_cfg *oc) { float x, y, w, h; @@ -829,8 +670,7 @@ omap4_hwc_apply_transform(float transform[2][3],struct dss2_ovl_cfg *oc) oc->win.h = m_round(h > 0 ? h : -h); } -static void -omap4_hwc_adjust_ext_layer(omap4_hwc_ext_t *ext, struct dss2_ovl_info *ovl) +static void adjust_ext_layer(omap_hwc_ext_t *ext, struct dss2_ovl_info *ovl) { struct dss2_ovl_cfg *oc = &ovl->cfg; @@ -841,7 +681,7 @@ omap4_hwc_adjust_ext_layer(omap4_hwc_ext_t *ext, struct dss2_ovl_info *ovl) return; } - omap4_hwc_apply_transform(ext->m, oc); + apply_transform(ext->m, oc); /* combining transformations: F^a*R^b*F^i*R^j = F^(a+b)*R^(j+b*(-1)^i), because F*R = R^(-1)*F */ oc->rotation += (oc->mirror ? -1 : 1) * ext->current.rotation; @@ -852,8 +692,7 @@ omap4_hwc_adjust_ext_layer(omap4_hwc_ext_t *ext, struct dss2_ovl_info *ovl) static struct dsscomp_platform_info limits; -static void -omap4_hwc_adjust_primary_display_layer(omap4_hwc_device_t *hwc_dev, struct dss2_ovl_info *ovl) +static void adjust_primary_display_layer(omap_hwc_device_t *hwc_dev, struct dss2_ovl_info *ovl) { struct dss2_ovl_cfg *oc = &ovl->cfg; @@ -862,35 +701,35 @@ omap4_hwc_adjust_primary_display_layer(omap4_hwc_device_t *hwc_dev, struct dss2_ return; } - omap4_hwc_apply_transform(hwc_dev->primary_m, oc); + apply_transform(hwc_dev->primary_m, oc); /* combining transformations: F^a*R^b*F^i*R^j = F^(a+b)*R^(j+b*(-1)^i), because F*R = R^(-1)*F */ oc->rotation += (oc->mirror ? -1 : 1) * hwc_dev->primary_rotation; oc->rotation &= 3; } -static int omap4_hwc_can_scale(__u32 src_w, __u32 src_h, __u32 dst_w, __u32 dst_h, int is_2d, - struct dsscomp_display_info *dis, struct dsscomp_platform_info *limits, - __u32 pclk, void *handle) +static bool can_scale(uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h, bool is_2d, + struct dsscomp_display_info *dis, struct dsscomp_platform_info *limits, + uint32_t pclk, IMG_native_handle_t *handle) { - __u32 fclk = limits->fclk / 1000; - __u32 min_src_w = DIV_ROUND_UP(src_w, is_2d ? limits->max_xdecim_2d : limits->max_xdecim_1d); - __u32 min_src_h = DIV_ROUND_UP(src_h, is_2d ? limits->max_ydecim_2d : limits->max_ydecim_1d); + uint32_t fclk = limits->fclk / 1000; + uint32_t min_src_w = DIV_ROUND_UP(src_w, is_2d ? limits->max_xdecim_2d : limits->max_xdecim_1d); + uint32_t min_src_h = DIV_ROUND_UP(src_h, is_2d ? limits->max_ydecim_2d : limits->max_ydecim_1d); /* ERRATAs */ /* cannot render 1-width layers on DSI video mode panels - we just disallow all 1-width LCD layers */ if (dis->channel != OMAP_DSS_CHANNEL_DIGIT && dst_w < limits->min_width) - return 0; + return false; /* NOTE: no support for checking YUV422 layers that are tricky to scale */ /* FIXME: limit vertical downscale well below theoretical limit as we saw display artifacts */ if (dst_h < src_h / 4) - return 0; + return false; /* max downscale */ if (dst_h * limits->max_downscale < min_src_h) - return 0; + return false; /* for manual panels pclk is 0, and there are no pclk based scaling limits */ if (!pclk) @@ -898,11 +737,11 @@ static int omap4_hwc_can_scale(__u32 src_w, __u32 src_h, __u32 dst_w, __u32 dst_ /* :HACK: limit horizontal downscale well below theoretical limit as we saw display artifacts */ if (dst_w * 4 < src_w) - return 0; + return false; if (handle) - if (get_rgb_bpp(handle) == 32 && src_w > 1280 && dst_w * 3 < src_w) - return 0; + if (get_format_bpp(handle->iFormat) == 32 && src_w > 1280 && dst_w * 3 < src_w) + return false; /* max horizontal downscale is 4, or the fclk/pixclk */ if (fclk > pclk * limits->max_downscale) @@ -910,13 +749,13 @@ static int omap4_hwc_can_scale(__u32 src_w, __u32 src_h, __u32 dst_w, __u32 dst_ /* for small parts, we need to use integer fclk/pixclk */ if (src_w < limits->integer_scale_ratio_limit) fclk = fclk / pclk * pclk; - if ((__u32) dst_w * fclk < min_src_w * pclk) - return 0; + if ((uint32_t) dst_w * fclk < min_src_w * pclk) + return false; - return 1; + return true; } -static int omap4_hwc_can_scale_layer(omap4_hwc_device_t *hwc_dev, hwc_layer_1_t *layer, IMG_native_handle_t *handle) +static bool can_scale_layer(omap_hwc_device_t *hwc_dev, hwc_layer_1_t *layer, IMG_native_handle_t *handle) { int src_w = WIDTH(layer->sourceCrop); int src_h = HEIGHT(layer->sourceCrop); @@ -929,40 +768,38 @@ static int omap4_hwc_can_scale_layer(omap4_hwc_device_t *hwc_dev, hwc_layer_1_t /* NOTE: layers should be able to be scaled externally since framebuffer is able to be scaled on selected external resolution */ - return omap4_hwc_can_scale(src_w, src_h, dst_w, dst_h, is_NV12(handle), &hwc_dev->fb_dis, &limits, - hwc_dev->fb_dis.timings.pixel_clock, handle); + return can_scale(src_w, src_h, dst_w, dst_h, is_NV12(handle), &hwc_dev->fb_dis, &limits, + hwc_dev->fb_dis.timings.pixel_clock, handle); } -static int omap4_hwc_is_valid_layer(omap4_hwc_device_t *hwc_dev, - hwc_layer_1_t *layer, - IMG_native_handle_t *handle) +static bool is_valid_layer(omap_hwc_device_t *hwc_dev, hwc_layer_1_t *layer, IMG_native_handle_t *handle) { /* Skip layers are handled by SF */ if ((layer->flags & HWC_SKIP_LAYER) || !handle) - return 0; + return false; - if (!omap4_hwc_is_valid_format(handle->iFormat)) - return 0; + if (!is_valid_format(handle->iFormat)) + return false; /* 1D buffers: no transform, must fit in TILER slot */ if (!is_NV12(handle)) { if (layer->transform) - return 0; + return false; if (mem1d(handle) > limits.tiler1d_slot_size) - return 0; + return false; } - return omap4_hwc_can_scale_layer(hwc_dev, layer, handle); + return can_scale_layer(hwc_dev, layer, handle); } -static __u32 add_scaling_score(__u32 score, - __u32 xres, __u32 yres, __u32 refresh, - __u32 ext_xres, __u32 ext_yres, - __u32 mode_xres, __u32 mode_yres, __u32 mode_refresh) +static uint32_t add_scaling_score(uint32_t score, + uint32_t xres, uint32_t yres, uint32_t refresh, + uint32_t ext_xres, uint32_t ext_yres, + uint32_t mode_xres, uint32_t mode_yres, uint32_t mode_refresh) { - __u32 area = xres * yres; - __u32 ext_area = ext_xres * ext_yres; - __u32 mode_area = mode_xres * mode_yres; + uint32_t area = xres * yres; + uint32_t ext_area = ext_xres * ext_yres; + uint32_t mode_area = mode_xres * mode_yres; /* prefer to upscale (1% tolerance) [0..1] (insert after 1st bit) */ int upscale = (ext_xres >= xres * 99 / 100 && ext_yres >= yres * 99 / 100); @@ -993,15 +830,14 @@ static __u32 add_scaling_score(__u32 score, return score; } -static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, __u32 yres, - float xpy) +static int set_best_hdmi_mode(omap_hwc_device_t *hwc_dev, uint32_t xres, uint32_t yres, float xpy) { int dis_ix = hwc_dev->on_tv ? 0 : 1; struct _qdis { struct dsscomp_display_info dis; struct dsscomp_videomode modedb[32]; } d = { .dis = { .ix = dis_ix } }; - omap4_hwc_ext_t *ext = &hwc_dev->ext; + omap_hwc_ext_t *ext = &hwc_dev->ext; d.dis.modedb_len = sizeof(d.modedb) / sizeof(*d.modedb); int ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_QUERY_DISPLAY, &d); @@ -1012,7 +848,7 @@ static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, xres * yres == 0) return -EINVAL; - __u32 i, best = ~0, best_score = 0; + uint32_t i, best = ~0, best_score = 0; ext->width = d.dis.width_in_mm; ext->height = d.dis.height_in_mm; ext->xres = d.dis.timings.x_res; @@ -1024,13 +860,13 @@ static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, ext->yres = 480; } - __u32 ext_fb_xres, ext_fb_yres; + uint32_t ext_fb_xres, ext_fb_yres; for (i = 0; i < d.dis.modedb_len; i++) { - __u32 score = 0; - __u32 mode_xres = d.modedb[i].xres; - __u32 mode_yres = d.modedb[i].yres; - __u32 ext_width = d.dis.width_in_mm; - __u32 ext_height = d.dis.height_in_mm; + uint32_t score = 0; + uint32_t mode_xres = d.modedb[i].xres; + uint32_t mode_yres = d.modedb[i].yres; + uint32_t ext_width = d.dis.width_in_mm; + uint32_t ext_height = d.dis.height_in_mm; if (d.modedb[i].vmode & FB_VMODE_INTERLACED) mode_yres /= 2; @@ -1052,9 +888,9 @@ static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, /* we need to ensure that even TILER2D buffers can be scaled */ if (!d.modedb[i].pixclock || (d.modedb[i].vmode & ~FB_VMODE_INTERLACED) || - !omap4_hwc_can_scale(xres, yres, ext_fb_xres, ext_fb_yres, - 1, &d.dis, &limits, - 1000000000 / d.modedb[i].pixclock, NULL)) + !can_scale(xres, yres, ext_fb_xres, ext_fb_yres, + 1, &d.dis, &limits, + 1000000000 / d.modedb[i].pixclock, NULL)) continue; /* prefer CEA modes */ @@ -1062,7 +898,7 @@ static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, score = 1; /* prefer the same mode as we use for mirroring to avoid mode change */ - score = (score << 1) | (i == ~ext->mirror_mode && ext->avoid_mode_change); + score = (score << 1) | (i == ~ext->mirror_mode && ext->avoid_mode_change); score = add_scaling_score(score, xres, yres, 60, ext_fb_xres, ext_fb_yres, mode_xres, mode_yres, d.modedb[i].refresh ? : 1); @@ -1088,16 +924,16 @@ static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, ioctl(hwc_dev->dsscomp_fd, DSSCIOC_SETUP_DISPLAY, &sdis); ext->last_mode = ~best; } else { - __u32 ext_width = d.dis.width_in_mm; - __u32 ext_height = d.dis.height_in_mm; - __u32 ext_fb_xres, ext_fb_yres; + uint32_t ext_width = d.dis.width_in_mm; + uint32_t ext_height = d.dis.height_in_mm; + uint32_t ext_fb_xres, ext_fb_yres; get_max_dimensions(xres, yres, xpy, d.dis.timings.x_res, d.dis.timings.y_res, ext_width, ext_height, &ext_fb_xres, &ext_fb_yres); if (!d.dis.timings.pixel_clock || - !omap4_hwc_can_scale(xres, yres, ext_fb_xres, ext_fb_yres, - 1, &d.dis, &limits, - d.dis.timings.pixel_clock, NULL)) { + !can_scale(xres, yres, ext_fb_xres, ext_fb_yres, + 1, &d.dis, &limits, + d.dis.timings.pixel_clock, NULL)) { ALOGW("DSS scaler cannot support HDMI cloning"); return -1; } @@ -1110,20 +946,24 @@ static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, return 0; } - -static void gather_layer_statistics(omap4_hwc_device_t *hwc_dev, struct counts *num, hwc_display_contents_1_t *list) +static void gather_layer_statistics(omap_hwc_device_t *hwc_dev, hwc_display_contents_1_t *list) { - unsigned int i; + uint32_t i; + counts_t *num = &hwc_dev->counts; + + memset(num, 0, sizeof(*num)); + + num->composited_layers = list ? list->numHwLayers : 0; /* Figure out how many layers we can support via DSS */ for (i = 0; list && i < list->numHwLayers; i++) { hwc_layer_1_t *layer = &list->hwLayers[i]; IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; - __u32 s3d_layout_type = get_s3d_layout_type(layer); + uint32_t s3d_layout_type = get_s3d_layout_type(layer); layer->compositionType = HWC_FRAMEBUFFER; - if (omap4_hwc_is_valid_layer(hwc_dev, layer, handle)) { + if (is_valid_layer(hwc_dev, layer, handle)) { if (s3d_layout_type != eMono) { /* For now we can only handle 1 S3D layer, skip any additional ones */ @@ -1163,12 +1003,12 @@ static void gather_layer_statistics(omap4_hwc_device_t *hwc_dev, struct counts * num->mem += mem1d(handle); } } - hwc_dev->stats = *num; } -static void decide_supported_cloning(omap4_hwc_device_t *hwc_dev, struct counts *num) +static void decide_supported_cloning(omap_hwc_device_t *hwc_dev) { - omap4_hwc_ext_t *ext = &hwc_dev->ext; + omap_hwc_ext_t *ext = &hwc_dev->ext; + counts_t *num = &hwc_dev->counts; int nonscaling_ovls = NUM_NONSCALING_OVERLAYS; num->max_hw_overlays = MAX_HW_OVERLAYS; @@ -1232,11 +1072,12 @@ static void decide_supported_cloning(omap4_hwc_device_t *hwc_dev, struct counts num->max_scaling_overlays = num->max_hw_overlays - nonscaling_ovls; } -static int can_dss_render_all(omap4_hwc_device_t *hwc_dev, struct counts *num) +static bool can_dss_render_all(omap_hwc_device_t *hwc_dev) { - omap4_hwc_ext_t *ext = &hwc_dev->ext; - int on_tv = hwc_dev->on_tv || (ext->on_tv && ext->current.enabled); - int tform = ext->current.enabled && (ext->current.rotation || ext->current.hflip); + omap_hwc_ext_t *ext = &hwc_dev->ext; + counts_t *num = &hwc_dev->counts; + bool on_tv = hwc_dev->on_tv || (ext->on_tv && ext->current.enabled); + bool tform = ext->current.enabled && (ext->current.rotation || ext->current.hflip); return !hwc_dev->force_sgx && /* must have at least one layer if using composition bypass to get sync object */ @@ -1251,20 +1092,21 @@ static int can_dss_render_all(omap4_hwc_device_t *hwc_dev, struct counts *num) (!tform || (num->NV12 == num->possible_overlay_layers) || (num->NV12 && ext->current.docking)) && /* HDMI cannot display BGR */ - (num->BGR == 0 || (num->RGB == 0 && !on_tv) || !hwc_dev->flags_rgb_order); + (num->BGR == 0 || (num->RGB == 0 && !on_tv) || !hwc_dev->flags_rgb_order) && + /* If nv12_only flag is set DSS should only render NV12 */ + (!hwc_dev->flags_nv12_only || (num->BGR == 0 && num->RGB == 0)); } -static inline int can_dss_render_layer(omap4_hwc_device_t *hwc_dev, - hwc_layer_1_t *layer) +static inline bool can_dss_render_layer(omap_hwc_device_t *hwc_dev, hwc_layer_1_t *layer) { IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; - omap4_hwc_ext_t *ext = &hwc_dev->ext; - int cloning = ext->current.enabled && (!ext->current.docking || (handle!=NULL ? dockable(layer) : 0)); - int on_tv = hwc_dev->on_tv || (ext->on_tv && cloning); - int tform = cloning && (ext->current.rotation || ext->current.hflip); + omap_hwc_ext_t *ext = &hwc_dev->ext; + bool cloning = ext->current.enabled && (!ext->current.docking || (handle!=NULL ? dockable(layer) : 0)); + bool on_tv = hwc_dev->on_tv || (ext->on_tv && cloning); + bool tform = cloning && (ext->current.rotation || ext->current.hflip); - return omap4_hwc_is_valid_layer(hwc_dev, layer, handle) && + return is_valid_layer(hwc_dev, layer, handle) && /* cannot rotate non-NV12 layers on external display */ (!tform || is_NV12(handle)) && /* skip non-NV12 layers if also using SGX (if nv12_only flag is set) */ @@ -1281,9 +1123,9 @@ static inline int display_area(struct dss2_ovl_info *o) return o->cfg.win.w * o->cfg.win.h; } -static int clone_layer(omap4_hwc_device_t *hwc_dev, int ix) { +static int clone_layer(omap_hwc_device_t *hwc_dev, int ix) { struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data; - omap4_hwc_ext_t *ext = &hwc_dev->ext; + omap_hwc_ext_t *ext = &hwc_dev->ext; int ext_ovl_ix = dsscomp->num_ovls - hwc_dev->post2_layers; struct dss2_ovl_info *o = &dsscomp->ovls[dsscomp->num_ovls]; @@ -1316,20 +1158,20 @@ static int clone_layer(omap4_hwc_device_t *hwc_dev, int ix) { /* use distinct z values (to simplify z-order checking) */ o->cfg.zorder += hwc_dev->post2_layers; - omap4_hwc_adjust_ext_layer(&hwc_dev->ext, o); + adjust_ext_layer(&hwc_dev->ext, o); dsscomp->num_ovls++; return 0; } -static int clone_external_layer(omap4_hwc_device_t *hwc_dev, int ix) { +static int clone_external_layer(omap_hwc_device_t *hwc_dev, int ix) { struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data; - omap4_hwc_ext_t *ext = &hwc_dev->ext; + omap_hwc_ext_t *ext = &hwc_dev->ext; /* mirror only 1 external layer */ struct dss2_ovl_info *o = &dsscomp->ovls[ix]; /* full screen video after transformation */ - __u32 xres = o->cfg.crop.w, yres = o->cfg.crop.h; + uint32_t xres = o->cfg.crop.w, yres = o->cfg.crop.h; if ((ext->current.rotation + o->cfg.rotation) & 1) swap(xres, yres); float xpy = ext->lcd_xpy * o->cfg.win.w / o->cfg.win.h; @@ -1346,7 +1188,7 @@ static int clone_external_layer(omap4_hwc_device_t *hwc_dev, int ix) { xpy < ext->last_xpy * (1.f - ASPECT_RATIO_TOLERANCE) || xpy * (1.f - ASPECT_RATIO_TOLERANCE) > ext->last_xpy) { ALOGD("set up HDMI for %d*%d\n", xres, yres); - if (omap4_hwc_set_best_hdmi_mode(hwc_dev, xres, yres, xpy)) { + if (set_best_hdmi_mode(hwc_dev, xres, yres, xpy)) { ext->current.enabled = 0; return -ENODEV; } @@ -1366,8 +1208,7 @@ static int clone_external_layer(omap4_hwc_device_t *hwc_dev, int ix) { const char hdmiS3DTypePath[] = "/sys/devices/platform/omapdss/display1/s3d_type"; const char hdmiS3DEnablePath[] = "/sys/devices/platform/omapdss/display1/s3d_enable"; -static void -omap4_hwc_s3d_hdmi_enable(omap4_hwc_device_t *hwc_dev, bool enable) +static void enable_s3d_hdmi(omap_hwc_device_t *hwc_dev, bool enable) { size_t bytesWritten; char data; @@ -1422,10 +1263,8 @@ omap4_hwc_s3d_hdmi_enable(omap4_hwc_device_t *hwc_dev, bool enable) hwc_dev->ext.s3d_enabled = enable; } -static void -omap4_hwc_adjust_ext_s3d_layer(omap4_hwc_device_t *hwc_dev, - struct dss2_ovl_info *ovl, - bool leftView) +static void adjust_ext_s3d_layer(omap_hwc_device_t *hwc_dev, + struct dss2_ovl_info *ovl, bool left_view) { struct dss2_ovl_cfg *oc = &ovl->cfg; float x, y, w, h; @@ -1433,15 +1272,15 @@ omap4_hwc_adjust_ext_s3d_layer(omap4_hwc_device_t *hwc_dev, switch (hwc_dev->s3d_input_type) { case eSideBySide: oc->crop.w = oc->crop.w/2; - if ((leftView && hwc_dev->s3d_input_order == eRightViewFirst) || - (!leftView && hwc_dev->s3d_input_order == eLeftViewFirst)) { + if ((left_view && hwc_dev->s3d_input_order == eRightViewFirst) || + (!left_view && hwc_dev->s3d_input_order == eLeftViewFirst)) { oc->crop.x = oc->crop.x + oc->crop.w; } break; case eTopBottom: oc->crop.h = oc->crop.h/2; - if ((leftView && hwc_dev->s3d_input_order == eRightViewFirst) || - (!leftView && hwc_dev->s3d_input_order == eLeftViewFirst)) { + if ((left_view && hwc_dev->s3d_input_order == eRightViewFirst) || + (!left_view && hwc_dev->s3d_input_order == eLeftViewFirst)) { oc->crop.y = oc->crop.y + oc->crop.h; } break; @@ -1454,8 +1293,8 @@ omap4_hwc_adjust_ext_s3d_layer(omap4_hwc_device_t *hwc_dev, switch (hwc_dev->ext.s3d_type) { case eSideBySide: oc->win.w = oc->win.w/2; - if ((leftView && hwc_dev->ext.s3d_order == eRightViewFirst) || - (!leftView && hwc_dev->ext.s3d_order == eLeftViewFirst)) { + if ((left_view && hwc_dev->ext.s3d_order == eRightViewFirst) || + (!left_view && hwc_dev->ext.s3d_order == eLeftViewFirst)) { oc->win.x = oc->win.x/2 + hwc_dev->ext.xres/2; } else { oc->win.x = oc->win.x/2; @@ -1463,8 +1302,8 @@ omap4_hwc_adjust_ext_s3d_layer(omap4_hwc_device_t *hwc_dev, break; case eTopBottom: oc->win.h = oc->win.h/2; - if ((leftView && hwc_dev->ext.s3d_order == eRightViewFirst) || - (!leftView && hwc_dev->ext.s3d_order == eLeftViewFirst)) { + if ((left_view && hwc_dev->ext.s3d_order == eRightViewFirst) || + (!left_view && hwc_dev->ext.s3d_order == eLeftViewFirst)) { oc->win.y = oc->win.y/2 + hwc_dev->ext.yres/2; } else { oc->win.y = oc->win.y/2; @@ -1477,8 +1316,7 @@ omap4_hwc_adjust_ext_s3d_layer(omap4_hwc_device_t *hwc_dev, } } -static int -clone_s3d_external_layer(omap4_hwc_device_t *hwc_dev, int ix_s3d) +static int clone_s3d_external_layer(omap_hwc_device_t *hwc_dev, int ix_s3d) { struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data; int r; @@ -1502,21 +1340,21 @@ clone_s3d_external_layer(omap4_hwc_device_t *hwc_dev, int ix_s3d) return -EINVAL; } - omap4_hwc_adjust_ext_s3d_layer(hwc_dev, &dsscomp->ovls[dsscomp->num_ovls - 1], true); - omap4_hwc_adjust_ext_s3d_layer(hwc_dev, &dsscomp->ovls[dsscomp->num_ovls - 2], false); + adjust_ext_s3d_layer(hwc_dev, &dsscomp->ovls[dsscomp->num_ovls - 1], true); + adjust_ext_s3d_layer(hwc_dev, &dsscomp->ovls[dsscomp->num_ovls - 2], false); return 0; } -static int setup_mirroring(omap4_hwc_device_t *hwc_dev) +static int setup_mirroring(omap_hwc_device_t *hwc_dev) { - omap4_hwc_ext_t *ext = &hwc_dev->ext; + omap_hwc_ext_t *ext = &hwc_dev->ext; - __u32 xres = WIDTH(ext->mirror_region); - __u32 yres = HEIGHT(ext->mirror_region); + uint32_t xres = WIDTH(ext->mirror_region); + uint32_t yres = HEIGHT(ext->mirror_region); if (ext->current.rotation & 1) swap(xres, yres); - if (omap4_hwc_set_best_hdmi_mode(hwc_dev, xres, yres, ext->lcd_xpy)) + if (set_best_hdmi_mode(hwc_dev, xres, yres, ext->lcd_xpy)) return -ENODEV; set_ext_matrix(ext, ext->mirror_region); return 0; @@ -1552,22 +1390,17 @@ static void check_sync_fds(size_t numDisplays, hwc_display_contents_1_t** displa } } -static void blit_reset(omap4_hwc_device_t *hwc_dev, int flags) +static void blit_reset(omap_hwc_device_t *hwc_dev) { hwc_dev->blit_flags = 0; hwc_dev->blit_num = 0; hwc_dev->post2_blit_buffers = 0; hwc_dev->comp_data.blit_data.rgz_items = 0; - - /* We want to maintain the rgz dirty region data if there are no geometry changes */ - if (flags & HWC_GEOMETRY_CHANGED) - rgz_release(&grgz); } -static int blit_layers(omap4_hwc_device_t *hwc_dev, hwc_display_contents_1_t *list, int bufoff) +static bool blit_layers(omap_hwc_device_t *hwc_dev, hwc_display_contents_1_t *list, int bufoff) { - /* Do not blit if this frame will be composed entirely by the GPU */ - if (!list || hwc_dev->force_sgx) + if (!list || hwc_dev->ext.mirror.enabled) goto err_out; int rgz_in_op; @@ -1585,12 +1418,34 @@ static int blit_layers(omap4_hwc_device_t *hwc_dev, hwc_display_contents_1_t *li break; } + /* + * Request the layer identities to SurfaceFlinger, first figure out if the + * operation is supported + */ + if (!(list->flags & HWC_EXTENDED_API) || !hwc_dev->procs || + hwc_dev->procs->extension_cb(hwc_dev->procs, HWC_EXTENDED_OP_LAYERDATA, NULL, -1) != 0) + goto err_out; + + /* Check if we have enough space in the extended layer list */ + if ((sizeof(hwc_layer_extended_t) * list->numHwLayers) > sizeof(grgz_ext_layer_list)) + goto err_out; + + uint32_t i; + for (i = 0; i < list->numHwLayers; i++) { + hwc_layer_extended_t *ext_layer = &grgz_ext_layer_list.layers[i]; + ext_layer->idx = i; + if (hwc_dev->procs->extension_cb(hwc_dev->procs, HWC_EXTENDED_OP_LAYERDATA, + (void **) &ext_layer, sizeof(hwc_layer_extended_t)) != 0) + goto err_out; + } + rgz_in_params_t in = { .op = rgz_in_op, .data = { .hwc = { .dstgeom = &gscrngeom, .layers = list->hwLayers, + .extlayers = grgz_ext_layer_list.layers, .layerno = list->numHwLayers } } @@ -1603,7 +1458,7 @@ static int blit_layers(omap4_hwc_device_t *hwc_dev, hwc_display_contents_1_t *li if (rgz_in(&in, &grgz) != RGZ_ALL) goto err_out; - unsigned int i, count = 0; + uint32_t count = 0; for (i = 0; i < list->numHwLayers; i++) { if (list->hwLayers[i].compositionType != HWC_OVERLAY) { count++; @@ -1656,14 +1511,14 @@ static int blit_layers(omap4_hwc_device_t *hwc_dev, hwc_display_contents_1_t *li } list->hwLayers[i].hints &= ~HWC_HINT_CLEAR_FB; } - return 1; + return true; err_out: rgz_release(&grgz); - return 0; + return false; } -void debug_post2(omap4_hwc_device_t *hwc_dev, int nbufs) +void debug_post2(omap_hwc_device_t *hwc_dev, int nbufs) { if (!debugpost2) return; @@ -1677,7 +1532,7 @@ void debug_post2(omap4_hwc_device_t *hwc_dev, int nbufs) } } -static int free_tiler2d_buffers(omap4_hwc_device_t *hwc_dev) +static int free_tiler2d_buffers(omap_hwc_device_t *hwc_dev) { int i; @@ -1688,7 +1543,7 @@ static int free_tiler2d_buffers(omap4_hwc_device_t *hwc_dev) return 0; } -static int allocate_tiler2d_buffers(omap4_hwc_device_t *hwc_dev) +static int allocate_tiler2d_buffers(omap_hwc_device_t *hwc_dev) { int ret, i; size_t stride; @@ -1718,8 +1573,7 @@ handle_error: return -1; } - -static int omap4_hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDisplays, +static int hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDisplays, hwc_display_contents_1_t** displays) { if (!numDisplays || displays == NULL) { @@ -1727,24 +1581,24 @@ static int omap4_hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDispla } hwc_display_contents_1_t* list = displays[0]; // ignore displays beyond the first - omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev; + omap_hwc_device_t *hwc_dev = (omap_hwc_device_t *)dev; struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data; - struct counts num = { .composited_layers = list ? list->numHwLayers : 0 }; - unsigned int i, ix; + counts_t *num = &hwc_dev->counts; + uint32_t i, ix; pthread_mutex_lock(&hwc_dev->lock); memset(dsscomp, 0x0, sizeof(*dsscomp)); dsscomp->sync_id = sync_id++; - gather_layer_statistics(hwc_dev, &num, list); + gather_layer_statistics(hwc_dev, list); - decide_supported_cloning(hwc_dev, &num); + decide_supported_cloning(hwc_dev); /* phase 3 logic */ - if (can_dss_render_all(hwc_dev, &num)) { + if (can_dss_render_all(hwc_dev)) { /* All layers can be handled by the DSS -- don't use SGX for composition */ hwc_dev->use_sgx = 0; - hwc_dev->swap_rb = num.BGR != 0; + hwc_dev->swap_rb = num->BGR != 0; } else { /* Use SGX for composition plus first 3 layers that are DSS renderable */ hwc_dev->use_sgx = 1; @@ -1754,17 +1608,16 @@ static int omap4_hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDispla /* setup pipes */ int z = 0; int fb_z = -1; - int scaled_gfx = 0; int ix_docking = -1; int ix_s3d = -1; - - int blit_all = 0; - blit_reset(hwc_dev, list ? list->flags : 0); + bool scaled_gfx = false; + bool blit_all = false; + blit_reset(hwc_dev); /* If the SGX is used or we are going to blit something we need a framebuffer * and a DSS pipe */ - int needs_fb = hwc_dev->use_sgx; + bool needs_fb = hwc_dev->use_sgx; if (hwc_dev->blt_policy == BLTPOLICY_ALL) { /* Check if we can blit everything */ @@ -1772,6 +1625,8 @@ static int omap4_hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDispla if (blit_all) { needs_fb = 1; hwc_dev->use_sgx = 0; + /* No need to swap red and blue channels */ + hwc_dev->swap_rb = 0; } } @@ -1781,13 +1636,12 @@ static int omap4_hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDispla dsscomp->num_ovls = needs_fb ? 1 /*VID1*/ : 0 /*GFX*/; /* set up if DSS layers */ - unsigned int mem_used = 0; - hwc_dev->ovls_blending = 0; - for (i = 0; list && i < list->numHwLayers; i++) { + uint32_t mem_used = 0; + for (i = 0; list && i < list->numHwLayers && !blit_all; i++) { hwc_layer_1_t *layer = &list->hwLayers[i]; IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; - if (dsscomp->num_ovls < num.max_hw_overlays && + if (dsscomp->num_ovls < num->max_hw_overlays && can_dss_render_layer(hwc_dev, layer) && (!hwc_dev->force_sgx || /* render protected and dockable layers via DSS */ @@ -1815,13 +1669,13 @@ static int omap4_hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDispla hwc_dev->buffers[dsscomp->num_ovls] = layer->handle; //ALOGI("dss buffers[%d] = %p", dsscomp->num_ovls, hwc_dev->buffers[dsscomp->num_ovls]); - omap4_hwc_setup_layer(hwc_dev, - &dsscomp->ovls[dsscomp->num_ovls], - layer, - z, - handle->iFormat, - handle->iWidth, - handle->iHeight); + setup_layer(hwc_dev, + &dsscomp->ovls[dsscomp->num_ovls], + layer, + z, + handle->iFormat, + handle->iWidth, + handle->iHeight); dsscomp->ovls[dsscomp->num_ovls].cfg.ix = dsscomp->num_ovls + hwc_dev->primary_transform; dsscomp->ovls[dsscomp->num_ovls].addressing = OMAP_DSS_BUFADDR_LAYER_IX; @@ -1867,11 +1721,17 @@ static int omap4_hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDispla dsscomp->ovls[0].cfg.ix = dsscomp->num_ovls; if (hwc_dev->blt_policy == BLTPOLICY_DEFAULT) { + /* + * As long as we keep blitting on consecutive frames keep the regionizer + * state, if this is not possible the regionizer state is unreliable and + * we need to reset its state. + */ if (hwc_dev->use_sgx) { if (blit_layers(hwc_dev, list, dsscomp->num_ovls == 1 ? 0 : dsscomp->num_ovls)) { hwc_dev->use_sgx = 0; } - } + } else + rgz_release(&grgz); } /* If the SGX is not used and there is blit data we need a framebuffer and @@ -1880,7 +1740,7 @@ static int omap4_hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDispla if (needs_fb) { /* assign a z-layer for fb */ if (fb_z < 0) { - if (!hwc_dev->blt_policy != BLTPOLICY_DISABLED && num.composited_layers) + if (!hwc_dev->blt_policy != BLTPOLICY_DISABLED && num->composited_layers) ALOGE("**** should have assigned z-layer for fb"); fb_z = z++; } @@ -1891,11 +1751,11 @@ static int omap4_hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDispla if (hwc_dev->use_sgx) { hwc_dev->buffers[0] = NULL; } - omap4_hwc_setup_layer_base(&dsscomp->ovls[0].cfg, fb_z, - hwc_dev->fb_dev->base.format, - 1, /* FB is always premultiplied */ - hwc_dev->fb_dev->base.width, - hwc_dev->fb_dev->base.height); + setup_layer_base(&dsscomp->ovls[0].cfg, fb_z, + hwc_dev->fb_dev->base.format, + 1, /* FB is always premultiplied */ + hwc_dev->fb_dev->base.width, + hwc_dev->fb_dev->base.height); dsscomp->ovls[0].cfg.pre_mult_alpha = 1; dsscomp->ovls[0].addressing = OMAP_DSS_BUFADDR_LAYER_IX; dsscomp->ovls[0].ba = 0; @@ -1905,8 +1765,8 @@ static int omap4_hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDispla /* mirror layers */ hwc_dev->post2_layers = dsscomp->num_ovls; - omap4_hwc_ext_t *ext = &hwc_dev->ext; - if (ext->current.enabled && ((!num.protected && hwc_dev->ext_ovls) || + omap_hwc_ext_t *ext = &hwc_dev->ext; + if (ext->current.enabled && ((!num->protected && hwc_dev->ext_ovls) || (hwc_dev->ext_ovls_wanted && hwc_dev->ext_ovls >= hwc_dev->ext_ovls_wanted))) { if (ext->current.docking && ix_s3d >= 0) { if (clone_s3d_external_layer(hwc_dev, ix_s3d) == 0) { @@ -1932,9 +1792,10 @@ static int omap4_hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDispla } else if (ext->current.docking && ix_docking < 0 && ext->force_dock) { ix_docking = dsscomp->num_ovls; struct dss2_ovl_info *oi = &dsscomp->ovls[ix_docking]; - omap4_hwc_setup_layer_base(&oi->cfg, 0, HAL_PIXEL_FORMAT_BGRA_8888, 1, - dock_image.width, dock_image.height); - oi->cfg.stride = dock_image.rowbytes; + image_info_t *dock_image = get_dock_image(); + setup_layer_base(&oi->cfg, 0, HAL_PIXEL_FORMAT_BGRA_8888, 1, + dock_image->width, dock_image->height); + oi->cfg.stride = dock_image->rowbytes; if (clone_external_layer(hwc_dev, ix_docking) == 0) { oi->addressing = OMAP_DSS_BUFADDR_FB; oi->ba = 0; @@ -1960,11 +1821,11 @@ static int omap4_hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDispla if (hwc_dev->primary_transform) for (i = 0; i < dsscomp->num_ovls; i++) { if(dsscomp->ovls[i].cfg.mgr_ix == 0) - omap4_hwc_adjust_primary_display_layer(hwc_dev, &dsscomp->ovls[i]); + adjust_primary_display_layer(hwc_dev, &dsscomp->ovls[i]); } - omap4_hwc_s3d_hdmi_enable(hwc_dev, ix_s3d >= 0); + enable_s3d_hdmi(hwc_dev, ix_s3d >= 0); ext->last = ext->current; @@ -2007,21 +1868,21 @@ static int omap4_hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDispla ALOGD("prepare (%d) - %s (comp=%d, poss=%d/%d scaled, RGB=%d,BGR=%d,NV12=%d) (ext=%s%s%ddeg%s %dex/%dmx (last %dex,%din)\n", dsscomp->sync_id, hwc_dev->use_sgx ? "SGX+OVL" : "all-OVL", - num.composited_layers, - num.possible_overlay_layers, num.scaled_layers, - num.RGB, num.BGR, num.NV12, + num->composited_layers, + num->possible_overlay_layers, num->scaled_layers, + num->RGB, num->BGR, num->NV12, ext->on_tv ? "tv+" : "", ext->current.enabled ? ext->current.docking ? "dock+" : "mirror+" : "OFF+", ext->current.rotation * 90, ext->current.hflip ? "+hflip" : "", - hwc_dev->ext_ovls, num.max_hw_overlays, hwc_dev->last_ext_ovls, hwc_dev->last_int_ovls); + hwc_dev->ext_ovls, num->max_hw_overlays, hwc_dev->last_ext_ovls, hwc_dev->last_int_ovls); } pthread_mutex_unlock(&hwc_dev->lock); return 0; } -static void omap4_hwc_reset_screen(omap4_hwc_device_t *hwc_dev) +static void reset_screen(omap_hwc_device_t *hwc_dev) { static int first_set = 1; int ret; @@ -2049,7 +1910,7 @@ static void omap4_hwc_reset_screen(omap4_hwc_device_t *hwc_dev) } } -static int omap4_hwc_set(struct hwc_composer_device_1 *dev, +static int hwc_set(struct hwc_composer_device_1 *dev, size_t numDisplays, hwc_display_contents_1_t** displays) { if (!numDisplays || displays == NULL) { @@ -2063,17 +1924,17 @@ static int omap4_hwc_set(struct hwc_composer_device_1 *dev, dpy = list->dpy; sur = list->sur; } - omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev; + omap_hwc_device_t *hwc_dev = (omap_hwc_device_t *)dev; struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data; int err = 0; - int invalidate; + bool invalidate; pthread_mutex_lock(&hwc_dev->lock); - omap4_hwc_reset_screen(hwc_dev); + reset_screen(hwc_dev); invalidate = hwc_dev->ext_ovls_wanted && (hwc_dev->ext_ovls < hwc_dev->ext_ovls_wanted) && - (hwc_dev->stats.protected || !hwc_dev->ext_ovls); + (hwc_dev->counts.protected || !hwc_dev->ext_ovls); if (debug) dump_set_info(hwc_dev, list); @@ -2104,7 +1965,7 @@ static int omap4_hwc_set(struct hwc_composer_device_1 *dev, (hwc_dev->comp_data.blit_data.rgz_items * sizeof(struct rgz_blt_entry)); - unsigned int nbufs = hwc_dev->post2_layers; + uint32_t nbufs = hwc_dev->post2_layers; if (hwc_dev->post2_blit_buffers) { /* * We don't want to pass a NULL entry in the Post2, but we need to @@ -2114,7 +1975,7 @@ static int omap4_hwc_set(struct hwc_composer_device_1 *dev, nbufs += hwc_dev->post2_blit_buffers - 1; if (hwc_dev->post2_layers > 1) { - unsigned int i, j; + uint32_t i, j; for (i = 0; i < nbufs; i++) { hwc_dev->buffers[i] = hwc_dev->buffers[i+1]; } @@ -2151,9 +2012,9 @@ err_out: return err; } -static void omap4_hwc_dump(struct hwc_composer_device_1 *dev, char *buff, int buff_len) +static void hwc_dump(struct hwc_composer_device_1 *dev, char *buff, int buff_len) { - omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *)dev; + omap_hwc_device_t *hwc_dev = (omap_hwc_device_t *)dev; struct dsscomp_setup_dispc_data *dsscomp = &hwc_dev->comp_data.dsscomp_data; struct dump_buf log = { .buf = buff, @@ -2161,7 +2022,7 @@ static void omap4_hwc_dump(struct hwc_composer_device_1 *dev, char *buff, int bu }; int i; - dump_printf(&log, "omap4_hwc %d:\n", dsscomp->num_ovls); + dump_printf(&log, "omap_hwc %d:\n", dsscomp->num_ovls); dump_printf(&log, " idle timeout: %dms\n", hwc_dev->idle); for (i = 0; i < dsscomp->num_ovls; i++) { @@ -2186,125 +2047,9 @@ static void omap4_hwc_dump(struct hwc_composer_device_1 *dev, char *buff, int bu dump_printf(&log, "\n"); } -static void free_png_image(omap4_hwc_device_t *hwc_dev, struct omap4_hwc_img *img) -{ - memset(img, 0, sizeof(*img)); -} - -static int load_png_image(omap4_hwc_device_t *hwc_dev, char *path, struct omap4_hwc_img *img) +static int hwc_device_close(hw_device_t* device) { - void *ptr = NULL; - png_bytepp row_pointers = NULL; - - FILE *fd = fopen(path, "rb"); - if (!fd) { - ALOGE("failed to open PNG file %s: (%d)", path, errno); - return -EINVAL; - } - - const int SIZE_PNG_HEADER = 8; - __u8 header[SIZE_PNG_HEADER]; - fread(header, 1, SIZE_PNG_HEADER, fd); - if (png_sig_cmp(header, 0, SIZE_PNG_HEADER)) { - ALOGE("%s is not a PNG file", path); - goto fail; - } - - png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) - goto fail_alloc; - png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - goto fail_alloc; - - if (setjmp(png_jmpbuf(png_ptr))) - goto fail_alloc; - - png_init_io(png_ptr, fd); - png_set_sig_bytes(png_ptr, SIZE_PNG_HEADER); - png_set_user_limits(png_ptr, limits.max_width, limits.max_height); - png_read_info(png_ptr, info_ptr); - - __u8 bit_depth = png_get_bit_depth(png_ptr, info_ptr); - __u32 width = png_get_image_width(png_ptr, info_ptr); - __u32 height = png_get_image_height(png_ptr, info_ptr); - __u8 color_type = png_get_color_type(png_ptr, info_ptr); - - switch (color_type) { - case PNG_COLOR_TYPE_PALETTE: - png_set_palette_to_rgb(png_ptr); - png_set_filler(png_ptr, 128, PNG_FILLER_AFTER); - break; - case PNG_COLOR_TYPE_GRAY: - if (bit_depth < 8) { - png_set_expand_gray_1_2_4_to_8(png_ptr); - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) - png_set_tRNS_to_alpha(png_ptr); - } else { - png_set_filler(png_ptr, 128, PNG_FILLER_AFTER); - } - /* fall through */ - case PNG_COLOR_TYPE_GRAY_ALPHA: - png_set_gray_to_rgb(png_ptr); - break; - case PNG_COLOR_TYPE_RGB: - png_set_filler(png_ptr, 128, PNG_FILLER_AFTER); - /* fall through */ - case PNG_COLOR_TYPE_RGB_ALPHA: - png_set_bgr(png_ptr); - break; - default: - ALOGE("unsupported PNG color: %x", color_type); - goto fail_alloc; - } - - if (bit_depth == 16) - png_set_strip_16(png_ptr); - - const int bpp = 4; - img->size = ALIGN(width * height * bpp, 4096); - if (img->size > hwc_dev->img_mem_size) { - ALOGE("image does not fit into framebuffer area (%d > %d)", img->size, hwc_dev->img_mem_size); - goto fail_alloc; - } - img->ptr = hwc_dev->img_mem_ptr; - - row_pointers = calloc(height, sizeof(*row_pointers)); - if (!row_pointers) { - ALOGE("failed to allocate row pointers"); - goto fail_alloc; - } - __u32 i; - for (i = 0; i < height; i++) - row_pointers[i] = img->ptr + i * width * bpp; - png_set_rows(png_ptr, info_ptr, row_pointers); - png_read_update_info(png_ptr, info_ptr); - img->rowbytes = png_get_rowbytes(png_ptr, info_ptr); - - png_read_image(png_ptr, row_pointers); - png_read_end(png_ptr, NULL); - free(row_pointers); - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - fclose(fd); - img->width = width; - img->height = height; - return 0; - -fail_alloc: - free_png_image(hwc_dev, img); - free(row_pointers); - if (!png_ptr || !info_ptr) - ALOGE("failed to allocate PNG structures"); - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); -fail: - fclose(fd); - return -EINVAL; -} - - -static int omap4_hwc_device_close(hw_device_t* device) -{ - omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) device;; + omap_hwc_device_t *hwc_dev = (omap_hwc_device_t *) device;; if (hwc_dev) { if (hwc_dev->dsscomp_fd >= 0) @@ -2324,7 +2069,7 @@ static int omap4_hwc_device_close(hw_device_t* device) return 0; } -static int omap4_hwc_open_fb_hal(IMG_framebuffer_device_public_t **fb_dev) +static int open_fb_hal(IMG_framebuffer_device_public_t **fb_dev) { const struct hw_module_t *psModule; IMG_gralloc_module_public_t *psGrallocModule; @@ -2350,7 +2095,7 @@ err_out: return err; } -static void set_primary_display_transform_matrix(omap4_hwc_device_t *hwc_dev) +static void set_primary_display_transform_matrix(omap_hwc_device_t *hwc_dev) { /* create primary display translation matrix */ hwc_dev->fb_dis.ix = 0;/*Default display*/ @@ -2382,9 +2127,7 @@ static void set_primary_display_transform_matrix(omap4_hwc_device_t *hwc_dev) m_translate(hwc_dev->primary_m, lcd_w >> 1, lcd_h >> 1); } - - -static void handle_s3d_hotplug(omap4_hwc_ext_t *ext, int state) +static void handle_s3d_hotplug(omap_hwc_ext_t *ext, bool state) { struct edid_t *edid = NULL; if (state) { @@ -2414,20 +2157,19 @@ static void handle_s3d_hotplug(omap4_hwc_ext_t *ext, int state) } } - -static void handle_hotplug(omap4_hwc_device_t *hwc_dev) +static void handle_hotplug(omap_hwc_device_t *hwc_dev) { - omap4_hwc_ext_t *ext = &hwc_dev->ext; - __u8 state = ext->hdmi_state; + omap_hwc_ext_t *ext = &hwc_dev->ext; + bool state = ext->hdmi_state; /* Ignore external HDMI logic if the primary display is HDMI */ if (hwc_dev->on_tv) { ALOGI("Primary display is HDMI - skip clone/dock logic"); if (state) { - __u32 xres = hwc_dev->fb_dev->base.width; - __u32 yres = hwc_dev->fb_dev->base.height; - if (omap4_hwc_set_best_hdmi_mode(hwc_dev, xres, yres, ext->lcd_xpy)) { + uint32_t xres = hwc_dev->fb_dev->base.width; + uint32_t yres = hwc_dev->fb_dev->base.height; + if (set_best_hdmi_mode(hwc_dev, xres, yres, ext->lcd_xpy)) { ALOGE("Failed to set HDMI mode"); } set_primary_display_transform_matrix(hwc_dev); @@ -2474,10 +2216,7 @@ static void handle_hotplug(omap4_hwc_device_t *hwc_dev) ext->dock.rotation = 0; ext->dock.hflip = 0; - if (!dock_image.rowbytes) { - property_get("persist.hwc.dock_image", value, "/vendor/res/images/dock/dock.png"); - load_png_image(hwc_dev, value, &dock_image); - } + load_dock_image(); } /* select best mode for mirroring */ @@ -2523,7 +2262,7 @@ static void handle_hotplug(omap4_hwc_device_t *hwc_dev) hwc_dev->procs->invalidate(hwc_dev->procs); } -static void handle_uevents(omap4_hwc_device_t *hwc_dev, const char *buff, int len) +static void handle_uevents(omap_hwc_device_t *hwc_dev, const char *buff, int len) { int dock; int hdmi; @@ -2567,12 +2306,12 @@ static void handle_uevents(omap4_hwc_device_t *hwc_dev, const char *buff, int le } } -static void *omap4_hwc_hdmi_thread(void *data) +static void *hdmi_thread(void *data) { - omap4_hwc_device_t *hwc_dev = data; + omap_hwc_device_t *hwc_dev = data; static char uevent_desc[4096]; struct pollfd fds[2]; - int invalidate = 0; + bool invalidate = false; int timeout; int err; @@ -2635,18 +2374,17 @@ static void *omap4_hwc_hdmi_thread(void *data) return NULL; } -static void omap4_hwc_registerProcs(struct hwc_composer_device_1* dev, +static void hwc_registerProcs(struct hwc_composer_device_1* dev, hwc_procs_t const* procs) { - omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) dev; + omap_hwc_device_t *hwc_dev = (omap_hwc_device_t *) dev; hwc_dev->procs = (typeof(hwc_dev->procs)) procs; } -static int omap4_hwc_query(struct hwc_composer_device_1* dev, - int what, int* value) +static int hwc_query(struct hwc_composer_device_1* dev, int what, int* value) { - omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) dev; + omap_hwc_device_t *hwc_dev = (omap_hwc_device_t *) dev; switch (what) { case HWC_BACKGROUND_LAYER_SUPPORTED: @@ -2664,10 +2402,10 @@ static int omap4_hwc_query(struct hwc_composer_device_1* dev, return 0; } -static int omap4_hwc_event_control(struct hwc_composer_device_1* dev, +static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy, int event, int enabled) { - omap4_hwc_device_t *hwc_dev = (omap4_hwc_device_t *) dev; + omap_hwc_device_t *hwc_dev = (omap_hwc_device_t *) dev; switch (event) { case HWC_EVENT_VSYNC: @@ -2675,6 +2413,14 @@ static int omap4_hwc_event_control(struct hwc_composer_device_1* dev, int val = !!enabled; int err; + if (hwc_dev->use_sw_vsync) { + if (enabled) + start_sw_vsync(hwc_dev); + else + stop_sw_vsync(); + return 0; + } + err = ioctl(hwc_dev->fb_fd, OMAPFB_ENABLEVSYNC, &val); if (err < 0) return -errno; @@ -2686,18 +2432,17 @@ static int omap4_hwc_event_control(struct hwc_composer_device_1* dev, } } -static int omap4_hwc_blank(struct hwc_composer_device_1 *dev, int dpy, int blank) +static int hwc_blank(struct hwc_composer_device_1 *dev, int dpy, int blank) { // We're using an older method of screen blanking based on // early_suspend in the kernel. No need to do anything here. return 0; } -static int omap4_hwc_device_open(const hw_module_t* module, const char* name, - hw_device_t** device) +static int hwc_device_open(const hw_module_t* module, const char* name, hw_device_t** device) { - omap4_hwc_module_t *hwc_mod = (omap4_hwc_module_t *)module; - omap4_hwc_device_t *hwc_dev; + omap_hwc_module_t *hwc_mod = (omap_hwc_module_t *)module; + omap_hwc_device_t *hwc_dev; int err = 0; if (strcmp(name, HWC_HARDWARE_COMPOSER)) { @@ -2705,7 +2450,7 @@ static int omap4_hwc_device_open(const hw_module_t* module, const char* name, } if (!hwc_mod->fb_dev) { - err = omap4_hwc_open_fb_hal(&hwc_mod->fb_dev); + err = open_fb_hal(&hwc_mod->fb_dev); if (err) return err; @@ -2716,7 +2461,7 @@ static int omap4_hwc_device_open(const hw_module_t* module, const char* name, hwc_mod->fb_dev->bBypassPost = 1; } - hwc_dev = (omap4_hwc_device_t *)malloc(sizeof(*hwc_dev)); + hwc_dev = (omap_hwc_device_t *)malloc(sizeof(*hwc_dev)); if (hwc_dev == NULL) return -ENOMEM; @@ -2725,26 +2470,21 @@ static int omap4_hwc_device_open(const hw_module_t* module, const char* name, hwc_dev->base.common.tag = HARDWARE_DEVICE_TAG; hwc_dev->base.common.version = HWC_DEVICE_API_VERSION_1_0; - char value[PROPERTY_VALUE_MAX]; - property_get("ro.product.board", value, ""); - if (strncmp("blaze", value, PROPERTY_VALUE_MAX) == 0) { - ALOGI("Revert to legacy HWC API for fake vsync"); - hwc_dev->base.common.version = HWC_DEVICE_API_VERSION_0_2; + if (use_sw_vsync()) { + hwc_dev->use_sw_vsync = true; + init_sw_vsync(hwc_dev); } - if (strncmp("panda5", value, PROPERTY_VALUE_MAX) == 0) { - ALOGI("Revert to legacy HWC API for fake vsync"); - hwc_dev->base.common.version = HWC_DEVICE_API_VERSION_0_2; - } hwc_dev->base.common.module = (hw_module_t *)module; - hwc_dev->base.common.close = omap4_hwc_device_close; - hwc_dev->base.prepare = omap4_hwc_prepare; - hwc_dev->base.set = omap4_hwc_set; - hwc_dev->base.eventControl = omap4_hwc_event_control; - hwc_dev->base.blank = omap4_hwc_blank; - hwc_dev->base.query = omap4_hwc_query; - hwc_dev->base.registerProcs = omap4_hwc_registerProcs; - hwc_dev->base.dump = omap4_hwc_dump; + hwc_dev->base.common.close = hwc_device_close; + hwc_dev->base.prepare = hwc_prepare; + hwc_dev->base.set = hwc_set; + hwc_dev->base.eventControl = hwc_eventControl; + hwc_dev->base.blank = hwc_blank; + hwc_dev->base.dump = hwc_dump; + hwc_dev->base.registerProcs = hwc_registerProcs; + hwc_dev->base.query = hwc_query; + hwc_dev->fb_dev = hwc_mod->fb_dev; *device = &hwc_dev->base.common; @@ -2769,20 +2509,9 @@ static int omap4_hwc_device_open(const hw_module_t* module, const char* name, goto done; } - struct fb_fix_screeninfo fix; - if (ioctl(hwc_dev->fb_fd, FBIOGET_FSCREENINFO, &fix)) { - ALOGE("failed to get fb info (%d)", errno); - err = -errno; - goto done; - } - - hwc_dev->img_mem_size = fix.smem_len; - hwc_dev->img_mem_ptr = mmap(NULL, fix.smem_len, PROT_WRITE, MAP_SHARED, hwc_dev->fb_fd, 0); - if (hwc_dev->img_mem_ptr == MAP_FAILED) { - ALOGE("failed to map fb memory"); - err = -errno; + err = init_dock_image(hwc_dev, limits.max_width, limits.max_height); + if (err) goto done; - } /* Allocate the maximum buffers that we can receive from HWC */ hwc_dev->buffers = malloc(sizeof(buffer_handle_t) * MAX_HWC_LAYERS); @@ -2841,7 +2570,7 @@ static int omap4_hwc_device_open(const hw_module_t* module, const char* name, err = -errno; goto done; } - if (pthread_create(&hwc_dev->hdmi_thread, NULL, omap4_hwc_hdmi_thread, hwc_dev)) + if (pthread_create(&hwc_dev->hdmi_thread, NULL, hdmi_thread, hwc_dev)) { ALOGE("failed to create HDMI listening thread (%d): %m", errno); err = -errno; @@ -2851,6 +2580,7 @@ static int omap4_hwc_device_open(const hw_module_t* module, const char* name, /* get debug properties */ /* see if hwc is enabled at all */ + char value[PROPERTY_VALUE_MAX]; property_get("debug.hwc.rgb_order", value, "1"); hwc_dev->flags_rgb_order = atoi(value); property_get("debug.hwc.nv12_only", value, "0"); @@ -2890,7 +2620,7 @@ static int omap4_hwc_device_open(const hw_module_t* module, const char* name, } handle_hotplug(hwc_dev); - ALOGI("omap4_hwc_device_open(rgb_order=%d nv12_only=%d)", + ALOGI("open_device(rgb_order=%d nv12_only=%d)", hwc_dev->flags_rgb_order, hwc_dev->flags_nv12_only); int gc2d_fd = open("/dev/gcioctl", O_RDWR); @@ -2935,11 +2665,11 @@ done: return err; } -static struct hw_module_methods_t omap4_hwc_module_methods = { - .open = omap4_hwc_device_open, +static struct hw_module_methods_t module_methods = { + .open = hwc_device_open, }; -omap4_hwc_module_t HAL_MODULE_INFO_SYM = { +omap_hwc_module_t HAL_MODULE_INFO_SYM = { .base = { .common = { .tag = HARDWARE_MODULE_TAG, @@ -2948,7 +2678,7 @@ omap4_hwc_module_t HAL_MODULE_INFO_SYM = { .id = HWC_HARDWARE_MODULE_ID, .name = "OMAP 44xx Hardware Composer HAL", .author = "Texas Instruments", - .methods = &omap4_hwc_module_methods, + .methods = &module_methods, }, }, }; diff --git a/hwc/hwc_dev.h b/hwc/hwc_dev.h new file mode 100644 index 0000000..85fb346 --- /dev/null +++ b/hwc/hwc_dev.h @@ -0,0 +1,172 @@ +/* + * Copyright (C) Texas Instruments - http://www.ti.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __HWC_DEV__ +#define __HWC_DEV__ + +#include <stdint.h> +#include <stdbool.h> + +#include <hardware/hwcomposer.h> +#include <ui/S3DFormat.h> + +#include <linux/bltsville.h> +#include <video/dsscomp.h> +#include <video/omap_hwc.h> + +#include "hal_public.h" +#include "rgz_2d.h" + +struct ext_transform { + uint8_t rotation : 3; /* 90-degree clockwise rotations */ + uint8_t hflip : 1; /* flip l-r (after rotation) */ + uint8_t enabled : 1; /* cloning enabled */ + uint8_t docking : 1; /* docking vs. mirroring - used for state */ +}; +typedef struct ext_transform ext_transform_t; + +/* cloning support and state */ +struct omap_hwc_ext { + /* support */ + ext_transform_t mirror; /* mirroring settings */ + ext_transform_t dock; /* docking settings */ + float lcd_xpy; /* pixel ratio for UI */ + bool avoid_mode_change; /* use HDMI mode used for mirroring if possible */ + bool force_dock; /* must dock */ + + /* state */ + bool hdmi_state; /* whether HDMI is connected */ + bool on_tv; /* using a tv */ + ext_transform_t current; /* current settings */ + ext_transform_t last; /* last-used settings */ + + /* configuration */ + uint32_t last_xres_used; /* resolution and pixel ratio used for mode selection */ + uint32_t last_yres_used; + uint32_t last_mode; /* 2-s complement of last HDMI mode set, 0 if none */ + uint32_t mirror_mode; /* 2-s complement of mode used when mirroring */ + float last_xpy; + uint16_t width; /* external screen dimensions */ + uint16_t height; + uint32_t xres; /* external screen resolution */ + uint32_t yres; + float m[2][3]; /* external transformation matrix */ + hwc_rect_t mirror_region; /* region of screen to mirror */ + + bool s3d_enabled; + bool s3d_capable; + enum S3DLayoutType s3d_type; + enum S3DLayoutOrder s3d_order; +}; +typedef struct omap_hwc_ext omap_hwc_ext_t; + +enum bltpolicy { + BLTPOLICY_DISABLED = 0, + BLTPOLICY_DEFAULT = 1, /* Default blit policy */ + BLTPOLICY_ALL, /* Test mode to attempt to blit all */ +}; + +enum bltmode { + BLTMODE_PAINT = 0, /* Attempt to blit layer by layer */ + BLTMODE_REGION = 1, /* Attempt to blit layers via regions */ +}; + +struct omap_hwc_module { + hwc_module_t base; + + IMG_framebuffer_device_public_t *fb_dev; +}; +typedef struct omap_hwc_module omap_hwc_module_t; + +struct counts { + uint32_t possible_overlay_layers; + uint32_t composited_layers; + uint32_t scaled_layers; + uint32_t RGB; + uint32_t BGR; + uint32_t NV12; + uint32_t dockable; + uint32_t protected; + uint32_t s3d; + + uint32_t max_hw_overlays; + uint32_t max_scaling_overlays; + uint32_t mem; +}; +typedef struct counts counts_t; + +struct omap_hwc_device { + /* static data */ + hwc_composer_device_1_t base; + hwc_procs_t *procs; + pthread_t hdmi_thread; + pthread_mutex_t lock; + + IMG_framebuffer_device_public_t *fb_dev; + struct dsscomp_display_info fb_dis; + int fb_fd; /* file descriptor for /dev/fb0 */ + int dsscomp_fd; /* file descriptor for /dev/dsscomp */ + int hdmi_fb_fd; /* file descriptor for /dev/fb1 */ + int pipe_fds[2]; /* pipe to event thread */ + + int img_mem_size; /* size of fb for hdmi */ + void *img_mem_ptr; /* start of fb for hdmi */ + + int flags_rgb_order; + int flags_nv12_only; + float upscaled_nv12_limit; + + bool on_tv; /* using a tv */ + int force_sgx; + omap_hwc_ext_t ext; /* external mirroring data */ + int idle; + + float primary_m[2][3]; /* internal transformation matrix */ + int primary_transform; + int primary_rotation; + hwc_rect_t primary_region; + + buffer_handle_t *buffers; + bool use_sgx; + bool swap_rb; + uint32_t post2_layers; /* buffers used with DSS pipes*/ + uint32_t post2_blit_buffers; /* buffers used with blit */ + int ext_ovls; /* # of overlays on external display for current composition */ + int ext_ovls_wanted; /* # of overlays that should be on external display for current composition */ + int last_ext_ovls; /* # of overlays on external/internal display for last composition */ + int last_int_ovls; + + enum S3DLayoutType s3d_input_type; + enum S3DLayoutOrder s3d_input_order; + + enum bltmode blt_mode; + enum bltpolicy blt_policy; + + uint32_t blit_flags; + int blit_num; + struct omap_hwc_data comp_data; /* This is a kernel data structure */ + struct rgz_blt_entry blit_ops[RGZ_MAX_BLITS]; + + counts_t counts; + + int ion_fd; + struct ion_handle *ion_handles[2]; + bool use_sw_vsync; + +}; +typedef struct omap_hwc_device omap_hwc_device_t; + +#endif diff --git a/hwc/rgz_2d.c b/hwc/rgz_2d.c index 96c4374..ac4be96 100644 --- a/hwc/rgz_2d.c +++ b/hwc/rgz_2d.c @@ -28,32 +28,17 @@ #include <video/dsscomp.h> #include <video/omap_hwc.h> -#ifndef RGZ_TEST_INTEGRATION #include <cutils/log.h> #include <cutils/properties.h> #include <hardware/hwcomposer.h> -#include "hal_public.h" -#else -#include "hwcomposer.h" -#include "buffer_handle.h" -#define ALIGN(x,a) (((x) + (a) - 1L) & ~((a) - 1L)) -#define HW_ALIGN 32 -#endif - -#include "rgz_2d.h" - -#ifdef RGZ_TEST_INTEGRATION -extern void BVDump(const char* prefix, const char* tab, const struct bvbltparams* parms); -#define BVDUMP(p,t,parms) BVDump(p, t, parms) -#define HANDLE_TO_BUFFER(h) handle_to_buffer(h) -#define HANDLE_TO_STRIDE(h) handle_to_stride(h) -#else + +#include "hwc_dev.h" + static int rgz_handle_to_stride(IMG_native_handle_t *h); #define BVDUMP(p,t,parms) #define HANDLE_TO_BUFFER(h) NULL /* Needs to be meaningful for TILER & GFX buffers and NV12 */ #define HANDLE_TO_STRIDE(h) rgz_handle_to_stride(h) -#endif #define DSTSTRIDE(dstgeom) dstgeom->virtstride /* Borrowed macros from hwc.c vvv - consider sharing later */ @@ -75,19 +60,16 @@ static int rgz_handle_to_stride(IMG_native_handle_t *h); #define is_OPAQUE(format) ((format) == HAL_PIXEL_FORMAT_RGB_565 || (format) == HAL_PIXEL_FORMAT_RGBX_8888 || (format) == HAL_PIXEL_FORMAT_BGRX_8888) /* OUTP the means for grabbing diagnostic data */ -#ifndef RGZ_TEST_INTEGRATION #define OUTP ALOGI #define OUTE ALOGE -#else -#define OUTP(...) { printf(__VA_ARGS__); printf("\n"); fflush(stdout); } -#define OUTE OUTP -#define ALOGD_IF(debug, ...) { if (debug) OUTP(__VA_ARGS__); } -#endif #define IS_BVCMD(params) (params->op == RGZ_OUT_BVCMD_REGION || params->op == RGZ_OUT_BVCMD_PAINT) -/* Number of framebuffers to track */ -#define RGZ_NUM_FB 2 +#define RECT_INTERSECTS(a, b) (((a).bottom > (b).top) && ((a).top < (b).bottom) && ((a).right > (b).left) && ((a).left < (b).right)) + +/* Buffer indexes used to distinguish background and layers with the clear fb hint */ +#define RGZ_BACKGROUND_BUFFIDX -2 +#define RGZ_CLEARHINT_BUFFIDX -1 struct rgz_blts { struct rgz_blt_entry bvcmds[RGZ_MAX_BLITS]; @@ -100,16 +82,16 @@ static void rgz_blts_init(struct rgz_blts *blts); static void rgz_blts_free(struct rgz_blts *blts); static struct rgz_blt_entry* rgz_blts_get(struct rgz_blts *blts, rgz_out_params_t *params); static int rgz_blts_bvdirect(rgz_t* rgz, struct rgz_blts *blts, rgz_out_params_t *params); -static void rgz_get_src_rect(hwc_layer_t* layer, blit_rect_t *subregion_rect, blit_rect_t *res_rect); +static void rgz_get_src_rect(hwc_layer_1_t* layer, blit_rect_t *subregion_rect, blit_rect_t *res_rect); static int hal_to_ocd(int color); static int rgz_get_orientation(unsigned int transform); static int rgz_get_flip_flags(unsigned int transform, int use_src2_flags); -static int rgz_hwc_scaled(hwc_layer_t *layer); +static int rgz_hwc_scaled(hwc_layer_1_t *layer); int debug = 0; struct rgz_blts blts; /* Represents a screen sized background layer */ -static hwc_layer_t bg_layer; +static hwc_layer_1_t bg_layer; static void svgout_header(int htmlw, int htmlh, int coordw, int coordh) { @@ -169,7 +151,7 @@ static int get_layer_ops(blit_hregion_t *hregion, int subregion, int *bottom) if (!empty_rect(&hregion->blitrects[l][subregion])) { ops++; *bottom = l; - hwc_layer_t *layer = hregion->rgz_layers[l]->hwc_layer; + hwc_layer_1_t *layer = &hregion->rgz_layers[l]->hwc_layer; IMG_native_handle_t *h = (IMG_native_handle_t *)layer->handle; if ((layer->blending != HWC_BLENDING_PREMULT) || is_OPAQUE(h->iFormat)) break; @@ -228,7 +210,7 @@ static void rgz_out_svg(rgz_t *rgz, rgz_out_params_t *params) } /* XXX duplicate of hwc.c version */ -static void dump_layer(hwc_layer_t const* l, int iserr) +static void dump_layer(hwc_layer_1_t const* l, int iserr) { #define FMT(f) ((f) == HAL_PIXEL_FORMAT_TI_NV12 ? "NV12" : \ (f) == HAL_PIXEL_FORMAT_BGRX_8888 ? "xRGB32" : \ @@ -261,7 +243,7 @@ static void dump_all(rgz_layer_t *rgz_layers, unsigned int layerno, unsigned int { unsigned int i; for (i = 0; i < layerno; i++) { - hwc_layer_t *l = rgz_layers[i].hwc_layer; + hwc_layer_1_t *l = &rgz_layers[i].hwc_layer; OUTE("Layer %d", i); dump_layer(l, errlayer == i); } @@ -270,17 +252,18 @@ static void dump_all(rgz_layer_t *rgz_layers, unsigned int layerno, unsigned int static int rgz_out_bvdirect_paint(rgz_t *rgz, rgz_out_params_t *params) { int rv = 0; - unsigned int i; + int i; (void)rgz; rgz_blts_init(&blts); /* Begin from index 1 to remove the background layer from the output */ - for (i = 1; i < rgz->rgz_layerno; i++) { - rv = rgz_hwc_layer_blit(params, &rgz->rgz_layers[i]); + rgz_fb_state_t *cur_fb_state = &rgz->cur_fb_state; + for (i = 1; i < cur_fb_state->rgz_layerno; i++) { + rv = rgz_hwc_layer_blit(params, &cur_fb_state->rgz_layers[i]); if (rv) { OUTE("bvdirect_paint: error in layer %d: %d", i, rv); - dump_all(rgz->rgz_layers, rgz->rgz_layerno, i); + dump_all(cur_fb_state->rgz_layers, cur_fb_state->rgz_layerno, i); rgz_blts_free(&blts); return rv; } @@ -305,7 +288,7 @@ static int rgz_is_blending_disabled(rgz_out_params_t *params) return params->data.bvc.noblend; } -static void rgz_get_displayframe_rect(hwc_layer_t *layer, blit_rect_t *res_rect) +static void rgz_get_displayframe_rect(hwc_layer_1_t *layer, blit_rect_t *res_rect) { res_rect->left = layer->displayFrame.left; res_rect->top = layer->displayFrame.top; @@ -313,8 +296,149 @@ static void rgz_get_displayframe_rect(hwc_layer_t *layer, blit_rect_t *res_rect) res_rect->right = layer->displayFrame.right; } +/* + * Returns a clock-wise rotated view of the inner rectangle relative to + * the outer rectangle. The inner rectangle must be contained in the outer + * rectangle and coordinates must be relative to the top,left corner of the outer + * rectangle. + */ +static void rgz_get_rotated_view(blit_rect_t *outer_rect, blit_rect_t *inner_rect, + blit_rect_t *res_rect, int orientation) +{ + int outer_width = WIDTH(*outer_rect); + int outer_height = HEIGHT(*outer_rect); + int inner_width = WIDTH(*inner_rect); + int inner_height = HEIGHT(*inner_rect); + int delta_top = inner_rect->top - outer_rect->top; + int delta_left = inner_rect->left - outer_rect->left; + + /* Normalize the angle */ + orientation = (orientation % 360) + 360; + + /* + * Calculate the top,left offset of the inner rectangle inside the outer + * rectangle depending on the tranformation value. + */ + switch(orientation % 360) { + case 0: + res_rect->left = delta_left; + res_rect->top = delta_top; + break; + case 180: + res_rect->left = outer_width - inner_width - delta_left; + res_rect->top = outer_height - inner_height - delta_top; + break; + case 90: + res_rect->left = outer_height - inner_height - delta_top; + res_rect->top = delta_left; + break; + case 270: + res_rect->left = delta_top; + res_rect->top = outer_width - inner_width - delta_left; + break; + default: + OUTE("Invalid transform value %d", orientation); + } + + if (orientation % 180) + swap(inner_width, inner_height); + + res_rect->right = res_rect->left + inner_width; + res_rect->bottom = res_rect->top + inner_height; +} + +static void rgz_get_src_rect(hwc_layer_1_t* layer, blit_rect_t *subregion_rect, blit_rect_t *res_rect) +{ + if (rgz_hwc_scaled(layer)) { + /* + * If the layer is scaled we use the whole cropping rectangle from the + * source and just move the clipping rectangle for the region we want to + * blit, this is done to prevent any artifacts when blitting subregions of + * a scaled layer. + */ + res_rect->top = layer->sourceCrop.top; + res_rect->left = layer->sourceCrop.left; + res_rect->bottom = layer->sourceCrop.bottom; + res_rect->right = layer->sourceCrop.right; + return; + } + + blit_rect_t display_frame; + rgz_get_displayframe_rect(layer, &display_frame); + + /* + * Get the rotated subregion rectangle with respect to the display frame. + * In order to get this correctly we need to take in account the HWC + * orientation is clock-wise so to return to the 0 degree view we need to + * rotate counter-clock wise the orientation. For example, if the + * orientation is 90 we need to rotate -90 to return to a 0 degree view. + */ + int src_orientation = 0 - rgz_get_orientation(layer->transform); + rgz_get_rotated_view(&display_frame, subregion_rect, res_rect, src_orientation); + + /* + * In order to translate the resulting rectangle relative to the cropping + * rectangle the only thing left is account for the offset (result is already + * rotated). + */ + res_rect->left += layer->sourceCrop.left; + res_rect->right += layer->sourceCrop.left; + res_rect->top += layer->sourceCrop.top; + res_rect->bottom += layer->sourceCrop.top; +} + +/* + * Convert a destination geometry and rectangle to a specified rotated view. + * Since clipping rectangle is relative to the destination geometry it will be + * rotated as well. + */ +static void rgz_rotate_dst(struct rgz_blt_entry* e, int dst_orientation) +{ + struct bvsurfgeom *dstgeom = &e->dstgeom; + struct bvrect *dstrect = &e->bp.dstrect; + struct bvrect *cliprect = &e->bp.cliprect; + + /* + * Create a rectangle that represents the destination geometry (outter + * rectangle), destination and clipping rectangles (inner rectangles). + */ + blit_rect_t dstgeom_r; + dstgeom_r.top = dstgeom_r.left = 0; + dstgeom_r.bottom = dstgeom->height; + dstgeom_r.right = dstgeom->width; + + blit_rect_t dstrect_r; + dstrect_r.top = dstrect->top; + dstrect_r.left = dstrect->left; + dstrect_r.bottom = dstrect->top + dstrect->height; + dstrect_r.right = dstrect->left + dstrect->width; + + blit_rect_t cliprect_r; + cliprect_r.top = cliprect->top; + cliprect_r.left = cliprect->left; + cliprect_r.bottom = cliprect->top + cliprect->height; + cliprect_r.right = cliprect->left + cliprect->width; + + /* Get the CW rotated view of the destination rectangle */ + blit_rect_t res_rect; + rgz_get_rotated_view(&dstgeom_r, &dstrect_r, &res_rect, dst_orientation); + dstrect->left = res_rect.left; + dstrect->top = res_rect.top; + dstrect->width = WIDTH(res_rect); + dstrect->height = HEIGHT(res_rect); + + rgz_get_rotated_view(&dstgeom_r, &cliprect_r, &res_rect, dst_orientation); + cliprect->left = res_rect.left; + cliprect->top = res_rect.top; + cliprect->width = WIDTH(res_rect); + cliprect->height = HEIGHT(res_rect); + + if (dst_orientation % 180) + swap(e->dstgeom.width, e->dstgeom.height); +} + static void rgz_set_dst_data(rgz_out_params_t *params, blit_rect_t *subregion_rect, - struct rgz_blt_entry* e) + struct rgz_blt_entry* e, int dst_orientation) { struct bvsurfgeom *screen_geom; rgz_get_screen_info(params, &screen_geom); @@ -324,19 +448,58 @@ static void rgz_set_dst_data(rgz_out_params_t *params, blit_rect_t *subregion_re e->dstgeom.format = screen_geom->format; e->dstgeom.width = screen_geom->width; e->dstgeom.height = screen_geom->height; - e->dstgeom.orientation = screen_geom->orientation; + e->dstgeom.orientation = dst_orientation; e->dstgeom.virtstride = DSTSTRIDE(screen_geom); e->bp.dstrect.left = subregion_rect->left; e->bp.dstrect.top = subregion_rect->top; e->bp.dstrect.width = WIDTH(*subregion_rect); e->bp.dstrect.height = HEIGHT(*subregion_rect); + + /* Give a rotated buffer representation of the destination if requested */ + if (e->dstgeom.orientation) + rgz_rotate_dst(e, dst_orientation); +} + +/* Convert a source geometry and rectangle to a specified rotated view */ +static void rgz_rotate_src(struct rgz_blt_entry* e, int src_orientation, int is_src2) +{ + struct bvsurfgeom *srcgeom = is_src2 ? &e->src2geom : &e->src1geom; + struct bvrect *srcrect = is_src2 ? &e->bp.src2rect : &e->bp.src1rect; + + /* + * Create a rectangle that represents the source geometry (outter rectangle), + * source rectangle (inner rectangle). + */ + blit_rect_t srcgeom_r; + srcgeom_r.top = srcgeom_r.left = 0; + srcgeom_r.bottom = srcgeom->height; + srcgeom_r.right = srcgeom->width; + + blit_rect_t srcrect_r; + srcrect_r.top = srcrect->top; + srcrect_r.left = srcrect->left; + srcrect_r.bottom = srcrect->top + srcrect->height; + srcrect_r.right = srcrect->left + srcrect->width; + + /* Get the CW rotated view of the source rectangle */ + blit_rect_t res_rect; + rgz_get_rotated_view(&srcgeom_r, &srcrect_r, &res_rect, src_orientation); + + srcrect->left = res_rect.left; + srcrect->top = res_rect.top; + srcrect->width = WIDTH(res_rect); + srcrect->height = HEIGHT(res_rect); + + if (src_orientation % 180) + swap(srcgeom->width, srcgeom->height); } static void rgz_set_src_data(rgz_out_params_t *params, rgz_layer_t *rgz_layer, - blit_rect_t *subregion_rect, struct rgz_blt_entry* e, int is_src2) + blit_rect_t *subregion_rect, struct rgz_blt_entry* e, int src_orientation, + int is_src2) { - hwc_layer_t *hwc_layer = rgz_layer->hwc_layer; + hwc_layer_1_t *hwc_layer = &rgz_layer->hwc_layer; struct bvbuffdesc *srcdesc = is_src2 ? &e->src2desc : &e->src1desc; struct bvsurfgeom *srcgeom = is_src2 ? &e->src2geom : &e->src1geom; struct bvrect *srcrect = is_src2 ? &e->bp.src2rect : &e->bp.src1rect; @@ -349,10 +512,7 @@ static void rgz_set_src_data(rgz_out_params_t *params, rgz_layer_t *rgz_layer, srcgeom->format = hal_to_ocd(handle->iFormat); srcgeom->width = handle->iWidth; srcgeom->height = handle->iHeight; - srcgeom->orientation = rgz_get_orientation(hwc_layer->transform); srcgeom->virtstride = HANDLE_TO_STRIDE(handle); - if (hwc_layer->transform & HAL_TRANSFORM_ROT_90) - swap(srcgeom->width, srcgeom->height); /* Find out what portion of the src we want to use for the blit */ blit_rect_t res_rect; @@ -361,6 +521,13 @@ static void rgz_set_src_data(rgz_out_params_t *params, rgz_layer_t *rgz_layer, srcrect->top = res_rect.top; srcrect->width = WIDTH(res_rect); srcrect->height = HEIGHT(res_rect); + + /* Give a rotated buffer representation of this source if requested */ + if (src_orientation) { + srcgeom->orientation = src_orientation; + rgz_rotate_src(e, src_orientation, is_src2); + } else + srcgeom->orientation = 0; } /* @@ -397,17 +564,22 @@ static void rgz_set_src2_is_dst(rgz_out_params_t *params, struct rgz_blt_entry* e->bp.src2rect = e->bp.dstrect; } +static int rgz_is_layer_nv12(hwc_layer_1_t *layer) +{ + IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; + return is_NV12(handle->iFormat); +} + /* * Configure the scaling mode according to the layer format */ -static void rgz_cfg_scale_mode(struct rgz_blt_entry* e, hwc_layer_t *layer) +static void rgz_cfg_scale_mode(struct rgz_blt_entry* e, hwc_layer_1_t *layer) { /* * TODO: Revisit scaling mode assignment later, output between GPU and GC320 * seem different */ - IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; - e->bp.scalemode = is_NV12(handle->iFormat) ? BVSCALE_9x9_TAP : BVSCALE_BILINEAR; + e->bp.scalemode = rgz_is_layer_nv12(layer) ? BVSCALE_9x9_TAP : BVSCALE_BILINEAR; } /* @@ -417,7 +589,7 @@ static struct rgz_blt_entry* rgz_hwc_subregion_copy(rgz_out_params_t *params, blit_rect_t *subregion_rect, rgz_layer_t *rgz_src1) { struct rgz_blt_entry* e = rgz_blts_get(&blts, params); - hwc_layer_t *hwc_src1 = rgz_src1->hwc_layer; + hwc_layer_1_t *hwc_src1 = &rgz_src1->hwc_layer; e->bp.structsize = sizeof(struct bvbltparams); e->bp.op.rop = 0xCCCC; /* SRCCOPY */ e->bp.flags = BVFLAG_CLIP | BVFLAG_ROP; @@ -431,9 +603,21 @@ static struct rgz_blt_entry* rgz_hwc_subregion_copy(rgz_out_params_t *params, } else tmp_rect = *subregion_rect; - rgz_set_src_data(params, rgz_src1, &tmp_rect, e, 0); - rgz_set_dst_data(params, &tmp_rect, e); + int src1_orientation = rgz_get_orientation(hwc_src1->transform); + int dst_orientation = 0; + + if (rgz_is_layer_nv12(hwc_src1)) { + /* + * Leave NV12 as 0 degree and rotate destination instead, this is done + * because of a GC limitation. Rotate destination CW. + */ + dst_orientation = 360 - src1_orientation; + src1_orientation = 0; + } + + rgz_set_src_data(params, rgz_src1, &tmp_rect, e, src1_orientation, 0); rgz_set_clip_rect(params, subregion_rect, e); + rgz_set_dst_data(params, &tmp_rect, e, dst_orientation); if((e->src1geom.format == OCDFMT_BGR124) || (e->src1geom.format == OCDFMT_RGB124) || @@ -452,7 +636,7 @@ static struct rgz_blt_entry* rgz_hwc_subregion_blend(rgz_out_params_t *params, blit_rect_t *subregion_rect, rgz_layer_t *rgz_src1, rgz_layer_t *rgz_src2) { struct rgz_blt_entry* e = rgz_blts_get(&blts, params); - hwc_layer_t *hwc_src1 = rgz_src1->hwc_layer; + hwc_layer_1_t *hwc_src1 = &rgz_src1->hwc_layer; e->bp.structsize = sizeof(struct bvbltparams); e->bp.op.blend = BVBLEND_SRC1OVER; e->bp.flags = BVFLAG_CLIP | BVFLAG_BLEND; @@ -466,20 +650,39 @@ static struct rgz_blt_entry* rgz_hwc_subregion_blend(rgz_out_params_t *params, } else tmp_rect = *subregion_rect; - rgz_set_src_data(params, rgz_src1, &tmp_rect, e, 0); - rgz_set_dst_data(params, &tmp_rect, e); + int src1_orientation = rgz_get_orientation(hwc_src1->transform); + int dst_orientation = 0; + + if (rgz_is_layer_nv12(hwc_src1)) { + /* + * Leave NV12 as 0 degree and rotate destination instead, this is done + * because of a GC limitation. Rotate destination CW. + */ + dst_orientation = 360 - src1_orientation; + src1_orientation = 0; + } + + rgz_set_src_data(params, rgz_src1, &tmp_rect, e, src1_orientation, 0); rgz_set_clip_rect(params, subregion_rect, e); + rgz_set_dst_data(params, &tmp_rect, e, dst_orientation); if (rgz_src2) { /* * NOTE: Due to an API limitation it's not possible to blend src1 and * src2 if both have scaling, hence only src1 is used for now */ - hwc_layer_t *hwc_src2 = rgz_src2->hwc_layer; + hwc_layer_1_t *hwc_src2 = &rgz_src2->hwc_layer; if (rgz_hwc_scaled(hwc_src2)) OUTE("src2 layer %p has scaling, this is not supported", hwc_src2); + /* + * We shouldn't receive a NV12 buffer as src2 at this point, this is an + * invalid parameter for the blend request + */ + if (rgz_is_layer_nv12(hwc_src2)) + OUTE("invalid input layer, src2 layer %p is NV12", hwc_src2); e->bp.flags |= rgz_get_flip_flags(hwc_src2->transform, 1); - rgz_set_src_data(params, rgz_src2, subregion_rect, e, 1); + int src2_orientation = rgz_get_orientation(hwc_src2->transform); + rgz_set_src_data(params, rgz_src2, subregion_rect, e, src2_orientation, 1); } else rgz_set_src2_is_dst(params, e); @@ -525,24 +728,24 @@ static void rgz_out_clrdst(rgz_out_params_t *params, blit_rect_t *rect) clear_rect.bottom = screen_geom->height; } - rgz_set_dst_data(params, &clear_rect, e); rgz_set_clip_rect(params, &clear_rect, e); + rgz_set_dst_data(params, &clear_rect, e, 0); } static int rgz_out_bvcmd_paint(rgz_t *rgz, rgz_out_params_t *params) { int rv = 0; + int i, j; params->data.bvc.out_blits = 0; params->data.bvc.out_nhndls = 0; rgz_blts_init(&blts); rgz_out_clrdst(params, NULL); - unsigned int i, j; - /* Begin from index 1 to remove the background layer from the output */ - for (i = 1, j = 0; i < rgz->rgz_layerno; i++) { - rgz_layer_t *rgz_layer = &rgz->rgz_layers[i]; - hwc_layer_t *l = rgz_layer->hwc_layer; + rgz_fb_state_t *cur_fb_state = &rgz->cur_fb_state; + for (i = 1, j = 0; i < cur_fb_state->rgz_layerno; i++) { + rgz_layer_t *rgz_layer = &cur_fb_state->rgz_layers[i]; + hwc_layer_1_t *l = &rgz_layer->hwc_layer; //OUTP("blitting meminfo %d", rgz->rgz_layers[i].buffidx); @@ -564,7 +767,7 @@ static int rgz_out_bvcmd_paint(rgz_t *rgz, rgz_out_params_t *params) rv = rgz_hwc_layer_blit(params, rgz_layer); if (rv) { OUTE("bvcmd_paint: error in layer %d: %d", i, rv); - dump_all(rgz->rgz_layers, rgz->rgz_layerno, i); + dump_all(cur_fb_state->rgz_layers, cur_fb_state->rgz_layerno, i); rgz_blts_free(&blts); return rv; } @@ -588,7 +791,7 @@ static int rgz_out_bvcmd_paint(rgz_t *rgz, rgz_out_params_t *params) return rv; } -static float getscalew(hwc_layer_t *layer) +static float getscalew(hwc_layer_1_t *layer) { int w = WIDTH(layer->sourceCrop); int h = HEIGHT(layer->sourceCrop); @@ -599,7 +802,7 @@ static float getscalew(hwc_layer_t *layer) return ((float)WIDTH(layer->displayFrame)) / (float)w; } -static float getscaleh(hwc_layer_t *layer) +static float getscaleh(hwc_layer_1_t *layer) { int w = WIDTH(layer->sourceCrop); int h = HEIGHT(layer->sourceCrop); @@ -610,31 +813,21 @@ static float getscaleh(hwc_layer_t *layer) return ((float)HEIGHT(layer->displayFrame)) / (float)h; } -static int rgz_bswap(int *a, int *b) -{ - if (*a > *b) { - int tmp = *b; - *b = *a; - *a = tmp; - return 1; - } - return 0; -} - /* - * Simple bubble sort on an array + * Simple bubble sort on an array, ascending order */ static void rgz_bsort(int *a, int len) { - int i, s; - - do { - s=0; - for (i=0; i+1<len; i++) { - if (rgz_bswap(&a[i], &a[i+1])) - s = 1; + int i, j; + for (i = 0; i < len; i++) { + for (j = 0; j < i; j++) { + if (a[i] < a[j]) { + int temp = a[i]; + a[i] = a[j]; + a[j] = temp; + } } - } while (s); + } } /* @@ -661,32 +854,7 @@ static int rgz_bunique(int *a, int len) return unique; } -static int rgz_hwc_layer_sortbyy(rgz_layer_t *ra, int rsz, int *out, int *width, int screen_height) -{ - int outsz = 0; - int i; - *width = 0; - for (i = 0; i < rsz; i++) { - hwc_layer_t *layer = ra[i].hwc_layer; - /* Maintain regions inside display boundaries */ - int top = layer->displayFrame.top; - int bottom = layer->displayFrame.bottom; - out[outsz++] = max(0, top); - out[outsz++] = min(bottom, screen_height); - int right = layer->displayFrame.right; - *width = *width > right ? *width : right; - } - rgz_bsort(out, outsz); - return outsz; -} - -static int rgz_hwc_intersects(blit_rect_t *a, hwc_rect_t *b) -{ - return ((a->bottom > b->top) && (a->top < b->bottom) && - (a->right > b->left) && (a->left < b->right)); -} - -static void rgz_gen_blitregions(blit_hregion_t *hregion, int screen_width) +static void rgz_gen_blitregions(rgz_t *rgz, blit_hregion_t *hregion, int screen_width) { /* * 1. Get the offsets (left/right positions) of each layer within the @@ -699,13 +867,19 @@ static void rgz_gen_blitregions(blit_hregion_t *hregion, int screen_width) int offsets[RGZ_SUBREGIONMAX]; int noffsets=0; int l, r; + + /* + * Add damaged region, then all layers. We are guaranteed to not go outside + * of offsets array boundaries at this point. + */ + offsets[noffsets++] = rgz->damaged_area.left; + offsets[noffsets++] = rgz->damaged_area.right; + for (l = 0; l < hregion->nlayers; l++) { - hwc_layer_t *layer = hregion->rgz_layers[l]->hwc_layer; + hwc_layer_1_t *layer = &hregion->rgz_layers[l]->hwc_layer; /* Make sure the subregion is not outside the boundaries of the screen */ - int left = layer->displayFrame.left; - int right = layer->displayFrame.right; - offsets[noffsets++] = max(0, left); - offsets[noffsets++] = min(right, screen_width); + offsets[noffsets++] = max(0, layer->displayFrame.left); + offsets[noffsets++] = min(layer->displayFrame.right, screen_width); } rgz_bsort(offsets, noffsets); noffsets = rgz_bunique(offsets, noffsets); @@ -721,8 +895,8 @@ static void rgz_gen_blitregions(blit_hregion_t *hregion, int screen_width) ALOGD_IF(debug, " sub l %d r %d", subregion.left, subregion.right); for (l = 0; l < hregion->nlayers; l++) { - hwc_layer_t *layer = hregion->rgz_layers[l]->hwc_layer; - if (rgz_hwc_intersects(&subregion, &layer->displayFrame)) { + hwc_layer_1_t *layer = &hregion->rgz_layers[l]->hwc_layer; + if (RECT_INTERSECTS(subregion, layer->displayFrame)) { hregion->blitrects[l][r] = subregion; @@ -736,7 +910,7 @@ static void rgz_gen_blitregions(blit_hregion_t *hregion, int screen_width) } } -static int rgz_hwc_scaled(hwc_layer_t *layer) +static int rgz_hwc_scaled(hwc_layer_1_t *layer) { int w = WIDTH(layer->sourceCrop); int h = HEIGHT(layer->sourceCrop); @@ -747,7 +921,7 @@ static int rgz_hwc_scaled(hwc_layer_t *layer) return WIDTH(layer->displayFrame) != w || HEIGHT(layer->displayFrame) != h; } -static int rgz_in_valid_hwc_layer(hwc_layer_t *layer) +static int rgz_in_valid_hwc_layer(hwc_layer_1_t *layer) { IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; if ((layer->flags & HWC_SKIP_LAYER) || !handle) @@ -792,35 +966,227 @@ static void rgz_delete_region_data(rgz_t *rgz){ rgz->state &= ~RGZ_REGION_DATA; } -static void rgz_handle_dirty_region(rgz_t *rgz, int reset_counters) +static rgz_fb_state_t* get_prev_fb_state(rgz_t *rgz) { - unsigned int i; - for (i = 0; i < rgz->rgz_layerno; i++) { - rgz_layer_t *rgz_layer = &rgz->rgz_layers[i]; - void *new_handle; + return &rgz->fb_states[rgz->fb_state_idx]; +} - /* - * We don't care about the handle for background and layers with the - * clear fb hint, but we want to maintain a layer state for dirty - * region handling. - */ - if (i == 0 || rgz_layer->buffidx == -1) - new_handle = (void*)0x1; - else - new_handle = (void*)rgz_layer->hwc_layer->handle; +static rgz_fb_state_t* get_next_fb_state(rgz_t *rgz) +{ + rgz->fb_state_idx = (rgz->fb_state_idx + 1) % RGZ_NUM_FB; + return &rgz->fb_states[rgz->fb_state_idx]; +} + +static void rgz_add_to_damaged_area(rgz_in_params_t *params, rgz_layer_t *rgz_layer, + blit_rect_t *damaged_area) +{ + struct bvsurfgeom *screen_geom = params->data.hwc.dstgeom; + hwc_layer_1_t *layer = &rgz_layer->hwc_layer; + + blit_rect_t screen_rect; + screen_rect.left = screen_rect.top = 0; + screen_rect.right = screen_geom->width; + screen_rect.bottom = screen_geom->height; + + /* Ignore the layer rectangle if it doesn't intersect the screen */ + if (!RECT_INTERSECTS(screen_rect, layer->displayFrame)) + return; + + /* Clip the layer rectangle to the screen geometry */ + blit_rect_t layer_rect; + rgz_get_displayframe_rect(layer, &layer_rect); + layer_rect.left = max(0, layer_rect.left); + layer_rect.top = max(0, layer_rect.top); + layer_rect.right = min(screen_rect.right, layer_rect.right); + layer_rect.bottom = min(screen_rect.bottom, layer_rect.bottom); + + /* Then add the rectangle to the damage area */ + if (empty_rect(damaged_area)) { + /* Adding for the first time */ + damaged_area->left = layer_rect.left; + damaged_area->top = layer_rect.top; + damaged_area->right = layer_rect.right; + damaged_area->bottom = layer_rect.bottom; + } else { + /* Grow current damaged area */ + damaged_area->left = min(damaged_area->left, layer_rect.left); + damaged_area->top = min(damaged_area->top, layer_rect.top); + damaged_area->right = max(damaged_area->right, layer_rect.right); + damaged_area->bottom = max(damaged_area->bottom, layer_rect.bottom); + } +} + +/* Search a layer with the specified identity in the passed array */ +static rgz_layer_t* rgz_find_layer(rgz_layer_t *rgz_layers, int rgz_layerno, + uint32_t layer_identity) +{ + int i; + for (i = 0; i < rgz_layerno; i++) { + rgz_layer_t *rgz_layer = &rgz_layers[i]; + /* Ignore background layer, it has no identity */ + if (rgz_layer->buffidx == RGZ_BACKGROUND_BUFFIDX) + continue; + if (rgz_layer->identity == layer_identity) + return rgz_layer; + } + return NULL; +} + +/* Determines if two layers with the same identity have changed its own window content */ +static int rgz_has_layer_content_changed(rgz_layer_t *cur_rgz_layer, rgz_layer_t *prev_rgz_layer) +{ + hwc_layer_1_t *cur_hwc_layer = &cur_rgz_layer->hwc_layer; + hwc_layer_1_t *prev_hwc_layer = &prev_rgz_layer->hwc_layer; + + /* The background has no identity and never changes */ + if (cur_rgz_layer->buffidx == RGZ_BACKGROUND_BUFFIDX && + prev_rgz_layer->buffidx == RGZ_BACKGROUND_BUFFIDX) + return 0; - if (reset_counters || new_handle != rgz_layer->dirty_hndl) { - rgz_layer->dirty_count = RGZ_NUM_FB; - rgz_layer->dirty_hndl = new_handle; + if (cur_rgz_layer->identity != prev_rgz_layer->identity) { + OUTE("%s: Invalid input, layer identities differ (current=%d, prev=%d)", + __func__, cur_rgz_layer->identity, prev_rgz_layer->identity); + return 1; + } + + /* If the layer has the clear fb hint we don't care about the content */ + if (cur_rgz_layer->buffidx == RGZ_CLEARHINT_BUFFIDX && + prev_rgz_layer->buffidx == RGZ_CLEARHINT_BUFFIDX) + return 0; + + /* Check if the layer content has changed */ + if (cur_hwc_layer->handle != prev_hwc_layer->handle || + cur_hwc_layer->transform != prev_hwc_layer->transform || + cur_hwc_layer->sourceCrop.top != prev_hwc_layer->sourceCrop.top || + cur_hwc_layer->sourceCrop.left != prev_hwc_layer->sourceCrop.left || + cur_hwc_layer->sourceCrop.bottom != prev_hwc_layer->sourceCrop.bottom || + cur_hwc_layer->sourceCrop.right != prev_hwc_layer->sourceCrop.right) + return 1; + + return 0; +} + +/* Determines if two layers with the same identity have changed their screen position */ +static int rgz_has_layer_frame_moved(rgz_layer_t *cur_rgz_layer, rgz_layer_t *target_rgz_layer) +{ + hwc_layer_1_t *cur_hwc_layer = &cur_rgz_layer->hwc_layer; + hwc_layer_1_t *target_hwc_layer = &target_rgz_layer->hwc_layer; + + if (cur_rgz_layer->identity != target_rgz_layer->identity) { + OUTE("%s: Invalid input, layer identities differ (current=%d, target=%d)", + __func__, cur_rgz_layer->identity, target_rgz_layer->identity); + return 1; + } + + if (cur_hwc_layer->displayFrame.top != target_hwc_layer->displayFrame.top || + cur_hwc_layer->displayFrame.left != target_hwc_layer->displayFrame.left || + cur_hwc_layer->displayFrame.bottom != target_hwc_layer->displayFrame.bottom || + cur_hwc_layer->displayFrame.right != target_hwc_layer->displayFrame.right) + return 1; + + return 0; +} + +static void rgz_handle_dirty_region(rgz_t *rgz, rgz_in_params_t *params, + rgz_fb_state_t* prev_fb_state, rgz_fb_state_t* target_fb_state) +{ + /* Reset damaged area */ + bzero(&rgz->damaged_area, sizeof(rgz->damaged_area)); + + int i; + rgz_fb_state_t *cur_fb_state = &rgz->cur_fb_state; + + for (i = 0; i < cur_fb_state->rgz_layerno; i++) { + rgz_layer_t *cur_rgz_layer = &cur_fb_state->rgz_layers[i]; + rgz_layer_t *prev_rgz_layer = NULL; + int layer_changed = 0; + + if (i == 0) { + /* + * Background is always zero, no need to search for it. If the previous state + * is empty reset the dirty count for the background layer. + */ + if (prev_fb_state->rgz_layerno) + prev_rgz_layer = &prev_fb_state->rgz_layers[0]; + } else { + /* Find out if this layer was present in the previous frame */ + prev_rgz_layer = rgz_find_layer(prev_fb_state->rgz_layers, + prev_fb_state->rgz_layerno, cur_rgz_layer->identity); + } + + /* Check if the layer is new or if the content changed from the previous frame */ + if (prev_rgz_layer && !rgz_has_layer_content_changed(cur_rgz_layer, prev_rgz_layer)) { + /* Copy previous dirty count */ + cur_rgz_layer->dirty_count = prev_rgz_layer->dirty_count; + cur_rgz_layer->dirty_count -= cur_rgz_layer->dirty_count ? 1 : 0; } else - rgz_layer->dirty_count -= rgz_layer->dirty_count ? 1 : 0; + cur_rgz_layer->dirty_count = RGZ_NUM_FB; + + /* If the layer is new, redraw the layer area */ + if (!prev_rgz_layer) { + rgz_add_to_damaged_area(params, cur_rgz_layer, &rgz->damaged_area); + continue; + } + + /* Nothing more to do with the background layer */ + if (i == 0) + continue; + + /* Find out if the layer is present in the target frame */ + rgz_layer_t *target_rgz_layer = rgz_find_layer(target_fb_state->rgz_layers, + target_fb_state->rgz_layerno, cur_rgz_layer->identity); + if (target_rgz_layer) { + /* Find out if the window size and position are different from the target frame */ + if (rgz_has_layer_frame_moved(cur_rgz_layer, target_rgz_layer)) { + /* + * Redraw both layer areas. This will effectively clear the area where + * this layer was in the target frame and force to draw the new layer + * location. + */ + rgz_add_to_damaged_area(params, cur_rgz_layer, &rgz->damaged_area); + rgz_add_to_damaged_area(params, target_rgz_layer, &rgz->damaged_area); + cur_rgz_layer->dirty_count = RGZ_NUM_FB; + } + } else { + /* If the layer is not in the target just draw it's new location */ + rgz_add_to_damaged_area(params, cur_rgz_layer, &rgz->damaged_area); + } } + + /* + * Add to damage area layers missing from the target frame to the current frame + * ignoring the background + */ + for (i = 1; i < target_fb_state->rgz_layerno; i++) { + rgz_layer_t *target_rgz_layer = &target_fb_state->rgz_layers[i]; + + rgz_layer_t *cur_rgz_layer = rgz_find_layer(cur_fb_state->rgz_layers, + cur_fb_state->rgz_layerno, target_rgz_layer->identity); + + /* Layers present in the target have been handled already in the loop above */ + if (cur_rgz_layer) + continue; + + /* The target layer is not present in the current frame, redraw its area */ + rgz_add_to_damaged_area(params, target_rgz_layer, &rgz->damaged_area); + } +} + +/* Adds the background layer in first the position of the passed fb state */ +static void rgz_add_background_layer(rgz_fb_state_t *fb_state) +{ + rgz_layer_t *rgz_layer = &fb_state->rgz_layers[0]; + rgz_layer->hwc_layer = bg_layer; + rgz_layer->buffidx = RGZ_BACKGROUND_BUFFIDX; + /* Set dummy handle to maintain dirty region state */ + rgz_layer->hwc_layer.handle = (void*) 0x1; } static int rgz_in_hwccheck(rgz_in_params_t *p, rgz_t *rgz) { - hwc_layer_t *layers = p->data.hwc.layers; + hwc_layer_1_t *layers = p->data.hwc.layers; + hwc_layer_extended_t *extlayers = p->data.hwc.extlayers; int layerno = p->data.hwc.layerno; rgz->state &= ~RGZ_STATE_INIT; @@ -837,15 +1203,6 @@ static int rgz_in_hwccheck(rgz_in_params_t *p, rgz_t *rgz) */ int l, memidx = 0; for (l = 0; l < layerno; l++) { - /* - * Workaround: If a NV12 layer is present in the list, don't even try - * to blit. There is a performance degradation while playing video and - * using GC at the same time. - */ - IMG_native_handle_t *handle = (IMG_native_handle_t *)layers[l].handle; - if (!(layers[l].flags & HWC_SKIP_LAYER) && handle && is_NV12(handle->iFormat)) - return -1; - if (layers[l].compositionType == HWC_OVERLAY) memidx++; } @@ -856,16 +1213,17 @@ static int rgz_in_hwccheck(rgz_in_params_t *p, rgz_t *rgz) * Insert the background layer at the beginning of the list, maintain a * state for dirty region handling */ - rgz_layer_t *rgz_layer = &rgz->rgz_layers[0]; - rgz_layer->hwc_layer = &bg_layer; + rgz_fb_state_t *cur_fb_state = &rgz->cur_fb_state; + rgz_add_background_layer(cur_fb_state); for (l = 0; l < layerno; l++) { if (layers[l].compositionType == HWC_FRAMEBUFFER) { candidates++; if (rgz_in_valid_hwc_layer(&layers[l]) && possible_blit < RGZ_INPUT_MAXLAYERS) { - rgz_layer_t *rgz_layer = &rgz->rgz_layers[possible_blit+1]; - rgz_layer->hwc_layer = &layers[l]; + rgz_layer_t *rgz_layer = &cur_fb_state->rgz_layers[possible_blit+1]; + rgz_layer->hwc_layer = layers[l]; + rgz_layer->identity = extlayers[l].identity; rgz_layer->buffidx = memidx++; possible_blit++; } @@ -879,9 +1237,12 @@ static int rgz_in_hwccheck(rgz_in_params_t *p, rgz_t *rgz) * Use only the layer rectangle as an input to regionize when the clear * fb hint is present, mark this layer to identify it. */ - rgz_layer_t *rgz_layer = &rgz->rgz_layers[possible_blit+1]; - rgz_layer->buffidx = -1; - rgz_layer->hwc_layer = &layers[l]; + rgz_layer_t *rgz_layer = &cur_fb_state->rgz_layers[possible_blit+1]; + rgz_layer->hwc_layer = layers[l]; + rgz_layer->identity = extlayers[l].identity; + rgz_layer->buffidx = RGZ_CLEARHINT_BUFFIDX; + /* Set dummy handle to maintain dirty region state */ + rgz_layer->hwc_layer.handle = (void*) 0x1; possible_blit++; } } @@ -891,46 +1252,68 @@ static int rgz_in_hwccheck(rgz_in_params_t *p, rgz_t *rgz) return -1; } - unsigned int blit_layers = possible_blit + 1; /* Account for background layer */ - int reset_dirty_counters = rgz->rgz_layerno != blit_layers ? 1 : 0; - /* - * The layers we are going to blit differ in number from the previous frame, - * we can't trust anymore the region data, calculate it again - */ - if (reset_dirty_counters) - rgz_delete_region_data(rgz); - rgz->state |= RGZ_STATE_INIT; - rgz->rgz_layerno = blit_layers; + cur_fb_state->rgz_layerno = possible_blit + 1; /* Account for background layer */ + + /* Get the target and previous frame geometries */ + rgz_fb_state_t* prev_fb_state = get_prev_fb_state(rgz); + rgz_fb_state_t* target_fb_state = get_next_fb_state(rgz); - rgz_handle_dirty_region(rgz, reset_dirty_counters); + /* Modifiy dirty counters and create the damaged region */ + rgz_handle_dirty_region(rgz, p, prev_fb_state, target_fb_state); + + /* Copy the current geometry to use it in the next frame */ + memcpy(target_fb_state->rgz_layers, cur_fb_state->rgz_layers, sizeof(rgz_layer_t) * cur_fb_state->rgz_layerno); + target_fb_state->rgz_layerno = cur_fb_state->rgz_layerno; return RGZ_ALL; } static int rgz_in_hwc(rgz_in_params_t *p, rgz_t *rgz) { + int i, j; int yentries[RGZ_SUBREGIONMAX]; int dispw; /* widest layer */ int screen_width = p->data.hwc.dstgeom->width; int screen_height = p->data.hwc.dstgeom->height; + rgz_fb_state_t *cur_fb_state = &rgz->cur_fb_state; if (!(rgz->state & RGZ_STATE_INIT)) { OUTE("rgz_process started with bad state"); return -1; } - /* If there is already region data avoid parsing it again */ - if (rgz->state & RGZ_REGION_DATA) { - return 0; + /* + * Figure out if there is enough space to store the top-bottom coordinates + * of each layer including the damaged area + */ + if (((cur_fb_state->rgz_layerno + 1) * 2) > RGZ_SUBREGIONMAX) { + OUTE("%s: Not enough space to store top-bottom coordinates of each layer (max %d, needed %d*2)", + __func__, RGZ_SUBREGIONMAX, cur_fb_state->rgz_layerno + 1); + return -1; } - int layerno = rgz->rgz_layerno; - - /* Find the horizontal regions */ - rgz_layer_t *rgz_layers = rgz->rgz_layers; - int ylen = rgz_hwc_layer_sortbyy(rgz_layers, layerno, yentries, &dispw, screen_height); + /* Delete the previous region data */ + rgz_delete_region_data(rgz); + /* + * Find the horizontal regions, add damaged area first which is already + * inside display boundaries + */ + int ylen = 0; + yentries[ylen++] = rgz->damaged_area.top; + yentries[ylen++] = rgz->damaged_area.bottom; + dispw = rgz->damaged_area.right; + + /* Add the top and bottom coordinates of each layer */ + for (i = 0; i < cur_fb_state->rgz_layerno; i++) { + hwc_layer_1_t *layer = &cur_fb_state->rgz_layers[i].hwc_layer; + /* Maintain regions inside display boundaries */ + yentries[ylen++] = max(0, layer->displayFrame.top); + yentries[ylen++] = min(layer->displayFrame.bottom, screen_height); + dispw = dispw > layer->displayFrame.right ? dispw : layer->displayFrame.right; + } + rgz_bsort(yentries, ylen); ylen = rgz_bunique(yentries, ylen); /* at this point we have an array of horizontal regions */ @@ -943,8 +1326,9 @@ static int rgz_in_hwc(rgz_in_params_t *p, rgz_t *rgz) } rgz->hregions = hregions; - ALOGD_IF(debug, "Allocated %d regions (sz = %d), layerno = %d", rgz->nhregions, rgz->nhregions * sizeof(blit_hregion_t), layerno); - int i, j; + ALOGD_IF(debug, "Allocated %d regions (sz = %d), layerno = %d", rgz->nhregions, + rgz->nhregions * sizeof(blit_hregion_t), cur_fb_state->rgz_layerno); + for (i = 0; i < rgz->nhregions; i++) { hregions[i].rect.top = yentries[i]; hregions[i].rect.bottom = yentries[i+1]; @@ -952,23 +1336,23 @@ static int rgz_in_hwc(rgz_in_params_t *p, rgz_t *rgz) hregions[i].rect.left = 0; hregions[i].rect.right = dispw > screen_width ? screen_width : dispw; hregions[i].nlayers = 0; - for (j = 0; j < layerno; j++) { - hwc_layer_t *layer = rgz_layers[j].hwc_layer; - if (rgz_hwc_intersects(&hregions[i].rect, &layer->displayFrame)) { + for (j = 0; j < cur_fb_state->rgz_layerno; j++) { + hwc_layer_1_t *layer = &cur_fb_state->rgz_layers[j].hwc_layer; + if (RECT_INTERSECTS(hregions[i].rect, layer->displayFrame)) { int l = hregions[i].nlayers++; - hregions[i].rgz_layers[l] = &rgz_layers[j]; + hregions[i].rgz_layers[l] = &cur_fb_state->rgz_layers[j]; } } } /* Calculate blit regions */ for (i = 0; i < rgz->nhregions; i++) { - rgz_gen_blitregions(&hregions[i], screen_width); + rgz_gen_blitregions(rgz, &hregions[i], screen_width); ALOGD_IF(debug, "hregion %3d: nsubregions %d", i, hregions[i].nsubregions); ALOGD_IF(debug, " : %d to %d: ", hregions[i].rect.top, hregions[i].rect.bottom); for (j = 0; j < hregions[i].nlayers; j++) - ALOGD_IF(debug, " %p ", hregions[i].rgz_layers[j]->hwc_layer); + ALOGD_IF(debug, " %p ", &hregions[i].rgz_layers[j]->hwc_layer); } rgz->state |= RGZ_REGION_DATA; return 0; @@ -981,7 +1365,7 @@ static int rgz_in_hwc(rgz_in_params_t *p, rgz_t *rgz) * dright, dbot, rot, flip, blending, scalew, scaleh, visrects * */ -static void rgz_print_layer(hwc_layer_t *l, int idx, int csv) +static void rgz_print_layer(hwc_layer_1_t *l, int idx, int csv) { char big_log[1024]; int e = sizeof(big_log); @@ -1079,11 +1463,11 @@ static void rgz_print_layer(hwc_layer_t *l, int idx, int csv) } } -static void rgz_print_layers(hwc_layer_list_t* list, int csv) +static void rgz_print_layers(hwc_display_contents_1_t* list, int csv) { size_t i; for (i = 0; i < list->numHwLayers; i++) { - hwc_layer_t *l = &list->hwLayers[i]; + hwc_layer_1_t *l = &list->hwLayers[i]; rgz_print_layer(l, i, csv); } } @@ -1110,53 +1494,10 @@ static int hal_to_ocd(int color) } } -/* - * The loadbltsville fn is only needed for testing, the bltsville shared - * libraries aren't planned to be used directly in production code here - */ static BVFN_MAP bv_map; static BVFN_BLT bv_blt; static BVFN_UNMAP bv_unmap; -#ifndef RGZ_TEST_INTEGRATION -gralloc_module_t const *gralloc; -#endif -#define BLTSVILLELIB "libbltsville_cpu.so" - -#ifdef RGZ_TEST_INTEGRATION -static int loadbltsville(void) -{ - void *hndl = dlopen(BLTSVILLELIB, RTLD_LOCAL | RTLD_LAZY); - if (!hndl) { - OUTE("Loading bltsville failed"); - return -1; - } - bv_map = (BVFN_MAP)dlsym(hndl, "bv_map"); - bv_blt = (BVFN_BLT)dlsym(hndl, "bv_blt"); - bv_unmap = (BVFN_UNMAP)dlsym(hndl, "bv_unmap"); - if(!bv_blt || !bv_map || !bv_unmap) { - OUTE("Missing bltsville fn %p %p %p", bv_map, bv_blt, bv_unmap); - return -1; - } - OUTP("Loaded %s", BLTSVILLELIB); - -#ifndef RGZ_TEST_INTEGRATION - hw_module_t const* module; - int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module); - if (err != 0) { - OUTE("Loading gralloc failed"); - return -1; - } - gralloc = (gralloc_module_t const *)module; -#endif - return 0; -} -#else -static int loadbltsville(void) { - return 0; -} -#endif -#ifndef RGZ_TEST_INTEGRATION static int rgz_handle_to_stride(IMG_native_handle_t *h) { int bpp = is_NV12(h->iFormat) ? 0 : (h->iFormat == HAL_PIXEL_FORMAT_RGB_565 ? 2 : 4); @@ -1164,10 +1505,6 @@ static int rgz_handle_to_stride(IMG_native_handle_t *h) return stride; } -#endif - -extern void BVDump(const char* prefix, const char* tab, const struct bvbltparams* parms); - static int rgz_get_orientation(unsigned int transform) { int orientation = 0; @@ -1195,11 +1532,7 @@ static int rgz_get_flip_flags(unsigned int transform, int use_src2_flags) static int rgz_hwc_layer_blit(rgz_out_params_t *params, rgz_layer_t *rgz_layer) { - static int loaded = 0; - if (!loaded) - loaded = loadbltsville() ? : 1; /* attempt load once */ - - hwc_layer_t* layer = rgz_layer->hwc_layer; + hwc_layer_1_t* layer = &rgz_layer->hwc_layer; blit_rect_t srcregion; rgz_get_displayframe_rect(layer, &srcregion); @@ -1212,72 +1545,19 @@ static int rgz_hwc_layer_blit(rgz_out_params_t *params, rgz_layer_t *rgz_layer) return 0; } -/* - * Calculate the src rectangle on the basis of the layer display, source crop - * and subregion rectangles. Additionally any rotation will be taken in - * account. The resulting rectangle is written in res_rect. - */ -static void rgz_get_src_rect(hwc_layer_t* layer, blit_rect_t *subregion_rect, blit_rect_t *res_rect) +static int rgz_can_blend_together(hwc_layer_1_t* src1_layer, hwc_layer_1_t* src2_layer) { - IMG_native_handle_t *handle = (IMG_native_handle_t *)layer->handle; - int res_left = 0; - int res_top = 0; - int delta_left; - int delta_top; - int res_width; - int res_height; - - /* - * If the layer is scaled we use the whole cropping rectangle from the - * source and just move the clipping rectangle for the region we want to - * blit, this is done to prevent any artifacts when blitting subregions of - * a scaled layer. If there is a transform, adjust the width and height - * accordingly to match the rotated buffer geometry. - */ - if (rgz_hwc_scaled(layer)) { - delta_top = 0; - delta_left = 0; - res_width = WIDTH(layer->sourceCrop); - res_height = HEIGHT(layer->sourceCrop); - if (layer->transform & HAL_TRANSFORM_ROT_90) - swap(res_width , res_height); - } else { - delta_top = subregion_rect->top - layer->displayFrame.top; - delta_left = subregion_rect->left - layer->displayFrame.left; - res_width = WIDTH(*subregion_rect); - res_height = HEIGHT(*subregion_rect); - } + /* If any layer is scaled we cannot blend both layers in one blit */ + if (rgz_hwc_scaled(src1_layer) || rgz_hwc_scaled(src2_layer)) + return 0; - /* - * Calculate the top, left offset from the source cropping rectangle - * depending on the rotation - */ - switch(layer->transform) { - case 0: - res_left = layer->sourceCrop.left + delta_left; - res_top = layer->sourceCrop.top + delta_top; - break; - case HAL_TRANSFORM_ROT_90: - res_left = handle->iHeight - layer->sourceCrop.bottom + delta_left; - res_top = layer->sourceCrop.left + delta_top; - break; - case HAL_TRANSFORM_ROT_180: - res_left = handle->iWidth - layer->sourceCrop.right + delta_left; - res_top = handle->iHeight - layer->sourceCrop.bottom + delta_top; - break; - case HAL_TRANSFORM_ROT_270: - res_left = layer->sourceCrop.top + delta_left; - res_top = handle->iWidth - layer->sourceCrop.right + delta_top; - break; - default: - OUTE("Invalid transform value %d", layer->transform); - } + /* NV12 buffers don't have alpha information on it */ + IMG_native_handle_t *src1_hndl = (IMG_native_handle_t *)src1_layer->handle; + IMG_native_handle_t *src2_hndl = (IMG_native_handle_t *)src2_layer->handle; + if (is_NV12(src1_hndl->iFormat) || is_NV12(src2_hndl->iFormat)) + return 0; - /* Resulting rectangle has the subregion dimensions */ - res_rect->left = res_left; - res_rect->top = res_top; - res_rect->right = res_left + res_width; - res_rect->bottom = res_top + res_height; + return 1; } static void rgz_batch_entry(struct rgz_blt_entry* e, unsigned int flag, unsigned int set) @@ -1287,12 +1567,9 @@ static void rgz_batch_entry(struct rgz_blt_entry* e, unsigned int flag, unsigned e->bp.batchflags |= set; } -static int rgz_hwc_subregion_blit(blit_hregion_t *hregion, int sidx, rgz_out_params_t *params) +static int rgz_hwc_subregion_blit(blit_hregion_t *hregion, int sidx, rgz_out_params_t *params, + blit_rect_t *damaged_area) { - static int loaded = 0; - if (!loaded) - loaded = loadbltsville() ? : 1; /* attempt load once */ - int lix; int ldepth = get_layer_ops(hregion, sidx, &lix); if (ldepth == 0) { @@ -1304,22 +1581,28 @@ static int rgz_hwc_subregion_blit(blit_hregion_t *hregion, int sidx, rgz_out_par } /* Determine if this region is dirty */ - int dirty = 0, dirtylix = lix; - while (dirtylix != -1) { - rgz_layer_t *rgz_layer = hregion->rgz_layers[dirtylix]; - if (rgz_layer->dirty_count){ - /* One of the layers is dirty, we need to generate blits for this subregion */ - dirty = 1; - break; + int dirty = 0; + blit_rect_t *subregion_rect = &hregion->blitrects[lix][sidx]; + if (RECT_INTERSECTS(*damaged_area, *subregion_rect)) { + /* The subregion intersects the damaged area, draw unconditionally */ + dirty = 1; + } else { + int dirtylix = lix; + while (dirtylix != -1) { + rgz_layer_t *rgz_layer = hregion->rgz_layers[dirtylix]; + if (rgz_layer->dirty_count){ + /* One of the layers is dirty, we need to generate blits for this subregion */ + dirty = 1; + break; + } + dirtylix = get_layer_ops_next(hregion, sidx, dirtylix); } - dirtylix = get_layer_ops_next(hregion, sidx, dirtylix); } - if (!dirty) return 0; /* Check if the bottom layer is the background */ - if (hregion->rgz_layers[lix]->hwc_layer == &bg_layer) { + if (hregion->rgz_layers[lix]->buffidx == RGZ_BACKGROUND_BUFFIDX) { if (ldepth == 1) { /* Background layer is the only operation, clear subregion */ rgz_out_clrdst(params, &hregion->blitrects[lix][sidx]); @@ -1337,7 +1620,7 @@ static int rgz_hwc_subregion_blit(blit_hregion_t *hregion, int sidx, rgz_out_par * See if the depth most layer needs to be ignored. If this layer is the * only operation, we need to clear this subregion. */ - if (hregion->rgz_layers[lix]->buffidx == -1) { + if (hregion->rgz_layers[lix]->buffidx == RGZ_CLEARHINT_BUFFIDX) { ldepth--; if (!ldepth) { rgz_out_clrdst(params, &hregion->blitrects[lix][sidx]); @@ -1359,36 +1642,81 @@ static int rgz_hwc_subregion_blit(blit_hregion_t *hregion, int sidx, rgz_out_par * We save a read and a write from the FB if we blend the bottom * two layers, we can do this only if both layers are not scaled */ + int prev_layer_scaled = 0; + int prev_layer_nv12 = 0; int first_batchflags = 0; - if (!rgz_hwc_scaled(hregion->rgz_layers[lix]->hwc_layer) && - !rgz_hwc_scaled(hregion->rgz_layers[s2lix]->hwc_layer)) { - e = rgz_hwc_subregion_blend(params, rect, hregion->rgz_layers[lix], - hregion->rgz_layers[s2lix]); - first_batchflags |= BVBATCH_SRC2; - } else { + rgz_layer_t *rgz_src1 = hregion->rgz_layers[lix]; + rgz_layer_t *rgz_src2 = hregion->rgz_layers[s2lix]; + if (rgz_can_blend_together(&rgz_src1->hwc_layer, &rgz_src2->hwc_layer)) + e = rgz_hwc_subregion_blend(params, rect, rgz_src1, rgz_src2); + else { /* Return index to the first operation and make a copy of the first layer */ lix = s2lix; - e = rgz_hwc_subregion_copy(params, rect, hregion->rgz_layers[lix]); - first_batchflags |= BVBATCH_OP | BVBATCH_SRC2; + rgz_src1 = hregion->rgz_layers[lix]; + e = rgz_hwc_subregion_copy(params, rect, rgz_src1); + /* + * First blit is a copy, the rest will be blends, hence the operation + * changed on the second blit. + */ + first_batchflags |= BVBATCH_OP; + prev_layer_nv12 = rgz_is_layer_nv12(&rgz_src1->hwc_layer); + prev_layer_scaled = rgz_hwc_scaled(&rgz_src1->hwc_layer); } + + /* + * Regardless if the first blit is a copy or blend, src2 may have changed + * on the second blit + */ + first_batchflags |= BVBATCH_SRC2 | BVBATCH_SRC2RECT_ORIGIN | BVBATCH_SRC2RECT_SIZE; + rgz_batch_entry(e, BVFLAG_BATCH_BEGIN, 0); /* Rest of layers blended with FB */ - int first = 1; while((lix = get_layer_ops_next(hregion, sidx, lix)) != -1) { - int batchflags = 0; - e = rgz_hwc_subregion_blend(params, rect, hregion->rgz_layers[lix], NULL); - if (first) { - first = 0; - batchflags |= first_batchflags; + int batchflags = first_batchflags; + first_batchflags = 0; + rgz_src1 = hregion->rgz_layers[lix]; + + /* Blend src1 into dst */ + e = rgz_hwc_subregion_blend(params, rect, rgz_src1, NULL); + + /* + * NOTE: After the first blit is configured, consequent blits are + * blend operations done with src1 and the destination, that is, + * src2 is the same as dst, any batchflag changed for the destination + * applies to src2 as well. + */ + + /* src1 parameters always change on every blit */ + batchflags |= BVBATCH_SRC1 | BVBATCH_SRC1RECT_ORIGIN| BVBATCH_SRC1RECT_SIZE; + + /* + * If the current/previous layer has scaling, destination rectangles + * likely changed as well as the scaling mode. Clipping rectangle + * remains the same as well as destination geometry. + */ + int cur_layer_scaled = rgz_hwc_scaled(&rgz_src1->hwc_layer); + if (cur_layer_scaled || prev_layer_scaled) { + batchflags |= BVBATCH_DSTRECT_ORIGIN | BVBATCH_DSTRECT_SIZE | + BVBATCH_SRC2RECT_ORIGIN | BVBATCH_SRC2RECT_SIZE | + BVBATCH_SCALE; } + prev_layer_scaled = cur_layer_scaled; + /* - * TODO: This will work when scaling is introduced, however we need - * to think on a better way to optimize this. + * If the current/previous layer is NV12, the destination geometry + * could have been rotated, hence the destination and clipping + * rectangles might have been trasformed to match the rotated + * destination geometry. */ - batchflags |= BVBATCH_SRC1 | BVBATCH_SRC1RECT_ORIGIN| BVBATCH_SRC1RECT_SIZE | - BVBATCH_DSTRECT_ORIGIN | BVBATCH_DSTRECT_SIZE | BVBATCH_SRC2RECT_ORIGIN | - BVBATCH_SRC2RECT_SIZE | BVBATCH_SCALE; + int cur_layer_nv12 = rgz_is_layer_nv12(&rgz_src1->hwc_layer); + if (cur_layer_nv12 || prev_layer_nv12) { + batchflags |= BVBATCH_DST | BVBATCH_DSTRECT_ORIGIN | BVBATCH_DSTRECT_SIZE | + BVBATCH_SRC2 | BVBATCH_SRC2RECT_ORIGIN | BVBATCH_SRC2RECT_SIZE | + BVBATCH_CLIPRECT; + } + prev_layer_nv12 = cur_layer_nv12; + rgz_batch_entry(e, BVFLAG_BATCH_CONTINUE, batchflags); } @@ -1489,7 +1817,7 @@ static int rgz_out_region(rgz_t *rgz, rgz_out_params_t *params) } for (s = 0; s < hregion->nsubregions; s++) { ALOGD_IF(debug, "h[%d] -> [%d]", i, s); - if (rgz_hwc_subregion_blit(hregion, s, params)) + if (rgz_hwc_subregion_blit(hregion, s, params, &rgz->damaged_area)) return -1; } } @@ -1497,16 +1825,16 @@ static int rgz_out_region(rgz_t *rgz, rgz_out_params_t *params) int rv = 0; if (IS_BVCMD(params)) { - unsigned int j; + int j; params->data.bvc.out_nhndls = 0; + rgz_fb_state_t *cur_fb_state = &rgz->cur_fb_state; /* Begin from index 1 to remove the background layer from the output */ - for (j = 1, i = 0; j < rgz->rgz_layerno; j++) { - rgz_layer_t *rgz_layer = &rgz->rgz_layers[j]; + for (j = 1, i = 0; j < cur_fb_state->rgz_layerno; j++) { + rgz_layer_t *rgz_layer = &cur_fb_state->rgz_layers[j]; /* We don't need the handles for layers marked as -1 */ if (rgz_layer->buffidx == -1) continue; - hwc_layer_t *layer = rgz_layer->hwc_layer; - params->data.bvc.out_hndls[i++] = layer->handle; + params->data.bvc.out_hndls[i++] = rgz_layer->hwc_layer.handle; params->data.bvc.out_nhndls++; } @@ -1531,12 +1859,11 @@ static int rgz_out_region(rgz_t *rgz, rgz_out_params_t *params) return rv; } -void rgz_profile_hwc(hwc_layer_list_t* list, int dispw, int disph) +void rgz_profile_hwc(hwc_display_contents_1_t* list, int dispw, int disph) { if (!list) /* A NULL composition list can occur */ return; -#ifndef RGZ_TEST_INTEGRATION static char regiondump2[PROPERTY_VALUE_MAX] = ""; char regiondump[PROPERTY_VALUE_MAX]; property_get("debug.2dhwc.region", regiondump, "0"); @@ -1555,11 +1882,6 @@ void rgz_profile_hwc(hwc_layer_list_t* list, int dispw, int disph) /* 0 - off, 1 - human readable, 2 - CSV */ property_get("debug.2dhwc.dumplayers", dumplayerdata, "0"); int dumplayers = atoi(dumplayerdata); -#else - char regiondump[] = ""; - int dumplayers = 1; - int dumpregions = 0; -#endif if (dumplayers && (list->flags & HWC_GEOMETRY_CHANGED)) { OUTP("<!-- BEGUN-LAYER-DUMP: %d -->", list->numHwLayers); rgz_print_layers(list, dumplayers == 1 ? 0 : 1); @@ -1623,7 +1945,6 @@ int rgz_get_screengeometry(int fd, struct bvsurfgeom *geom, int fmt) geom->height = fb_varinfo.yres; geom->virtstride = fb_fixinfo.line_length; geom->format = hal_to_ocd(fmt); - /* Always set to 0, src buffers will contain rotation values as needed */ geom->orientation = 0; return 0; } diff --git a/hwc/rgz_2d.h b/hwc/rgz_2d.h index 44867b8..de41b82 100644 --- a/hwc/rgz_2d.h +++ b/hwc/rgz_2d.h @@ -26,9 +26,13 @@ /* * Maximum number of layers the regionizer will accept as input. Account for an - * additional 'background layer' to generate empty subregion rectangles. + * additional 'background layer' to generate empty subregion rectangles and + * a damage region as well. */ -#define RGZ_INPUT_MAXLAYERS (RGZ_MAXLAYERS - 1) +#define RGZ_INPUT_MAXLAYERS (RGZ_MAXLAYERS - 2) + +/* Number of framebuffers to track */ +#define RGZ_NUM_FB 2 /* * Regionizer data @@ -50,7 +54,8 @@ int rgz_get_screengeometry(int fd, struct bvsurfgeom *geom, int fmt); struct rgz_in_hwc { int flags; int layerno; - hwc_layer_t *layers; + hwc_layer_1_t *layers; + hwc_layer_extended_t *extlayers; struct bvsurfgeom *dstgeom; }; @@ -61,6 +66,10 @@ typedef struct rgz_in_params { } data; } rgz_in_params_t; +typedef struct rgz_ext_layer_list { + hwc_layer_extended_t layers[RGZ_INPUT_MAXLAYERS]; +} rgz_ext_layer_list_t; + /* * Validate whether the HWC layers can be rendered * @@ -206,7 +215,7 @@ int rgz_out(rgz_t *rgz, rgz_out_params_t* params); /* * Produce instrumented logging of layer data */ -void rgz_profile_hwc(hwc_layer_list_t* list, int dispw, int disph); +void rgz_profile_hwc(hwc_display_contents_1_t* list, int dispw, int disph); /* * ---------------------------------- @@ -262,12 +271,17 @@ typedef struct blit_rect { #define RGZ_MAX_BLITS (RGZ_SUBREGIONMAX * RGZ_SUBREGIONMAX) typedef struct rgz_layer { - hwc_layer_t *hwc_layer; + hwc_layer_1_t hwc_layer; + uint32_t identity; int buffidx; int dirty_count; - void* dirty_hndl; } rgz_layer_t; +typedef struct rgz_fb_state { + int rgz_layerno; + rgz_layer_t rgz_layers[RGZ_MAXLAYERS]; +} rgz_fb_state_t; + typedef struct blit_hregion { blit_rect_t rect; rgz_layer_t *rgz_layers[RGZ_MAXLAYERS]; @@ -283,8 +297,10 @@ struct rgz { blit_hregion_t *hregions; int nhregions; int state; - unsigned int rgz_layerno; - rgz_layer_t rgz_layers[RGZ_MAXLAYERS]; + rgz_fb_state_t cur_fb_state; + int fb_state_idx; /* Target framebuffer index. Points to the fb where the blits will be applied to */ + rgz_fb_state_t fb_states[RGZ_NUM_FB]; /* Storage for previous framebuffer geometry states */ + blit_rect_t damaged_area; /* Area of the screen which will be redrawn unconditionally */ }; #endif /* __RGZ_2D__ */ diff --git a/hwc/sw_vsync.c b/hwc/sw_vsync.c new file mode 100644 index 0000000..cf24b31 --- /dev/null +++ b/hwc/sw_vsync.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) Texas Instruments - http://www.ti.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <errno.h> +#include <stdlib.h> +#include <stdarg.h> +#include <stdbool.h> +#include <sys/resource.h> +#include <pthread.h> +#include <time.h> + +#include <cutils/properties.h> +#include <cutils/log.h> +#include <utils/Timers.h> + +#include "hwc_dev.h" + +static pthread_t vsync_thread; +static pthread_mutex_t vsync_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t vsync_cond; +static bool vsync_loop_active = false; + +nsecs_t vsync_rate; + +static struct timespec diff(struct timespec start, struct timespec end) +{ + struct timespec temp; + if ((end.tv_nsec - start.tv_nsec) < 0) { + temp.tv_sec = end.tv_sec-start.tv_sec - 1; + temp.tv_nsec = 1000000000 + end.tv_nsec-start.tv_nsec; + } else { + temp.tv_sec = end.tv_sec - start.tv_sec; + temp.tv_nsec = end.tv_nsec - start.tv_nsec; + } + return temp; +} + +static void *vsync_loop(void *data) +{ + struct timespec tp, tp_next, tp_sleep; + nsecs_t now = 0, period = vsync_rate, next_vsync = 0, next_fake_vsync = 0, sleep = 0; + omap_hwc_device_t *hwc_dev = (omap_hwc_device_t *)data; + tp_sleep.tv_sec = tp_sleep.tv_nsec = 0; + bool reset_timers = true; + + setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY); + + for (;;) { + pthread_mutex_lock(&vsync_mutex); + period = vsync_rate; /* re-read rate */ + while (!vsync_loop_active) { + pthread_cond_wait(&vsync_cond, &vsync_mutex); + } + pthread_mutex_unlock(&vsync_mutex); + + clock_gettime(CLOCK_MONOTONIC, &tp); + now = (tp.tv_sec * 1000000000) + tp.tv_nsec; + next_vsync = next_fake_vsync; + sleep = next_vsync - now; + if (sleep < 0) { + /* we missed, find where the next vsync should be */ + sleep = (period - ((now - next_vsync) % period)); + next_vsync = now + sleep; + } + next_fake_vsync = next_vsync + period; + tp_next.tv_sec = (next_vsync / 1000000000); + tp_next.tv_nsec = (next_vsync % 1000000000); + tp_sleep = diff(tp, tp_next); + + nanosleep(&tp_sleep, NULL); + if (hwc_dev->procs && hwc_dev->procs->vsync) { + hwc_dev->procs->vsync(hwc_dev->procs, 0, next_vsync); + } + } + return NULL; +} + +bool use_sw_vsync() +{ + char board[PROPERTY_VALUE_MAX]; + bool rv = false; + property_get("ro.product.board", board, ""); + if ((strncmp("blaze", board, PROPERTY_VALUE_MAX) == 0) || + (strncmp("panda5", board, PROPERTY_VALUE_MAX) == 0)) { + /* TODO: panda5 really should support h/w vsync */ + rv = true; + } else { + char value[PROPERTY_VALUE_MAX]; + property_get("persist.hwc.sw_vsync", value, "0"); + int use_sw_vsync = atoi(value); + rv = use_sw_vsync > 0; + } + ALOGI("Expecting %s vsync for %s", rv ? "s/w" : "h/w", board); + return rv; +} + +void init_sw_vsync(omap_hwc_device_t *hwc_dev) +{ + pthread_cond_init(&vsync_cond, NULL); + pthread_create(&vsync_thread, NULL, vsync_loop, (void *)hwc_dev); +} + +void start_sw_vsync() +{ + char refresh_rate[PROPERTY_VALUE_MAX]; + property_get("persist.hwc.sw_vsync_rate", refresh_rate, "60"); + + pthread_mutex_lock(&vsync_mutex); + int rate = atoi(refresh_rate); + if (rate <= 0) + rate = 60; + vsync_rate = 1000000000 / rate; + if (vsync_loop_active) { + pthread_mutex_unlock(&vsync_mutex); + return; + } + vsync_loop_active = true; + pthread_mutex_unlock(&vsync_mutex); + pthread_cond_signal(&vsync_cond); +} + +void stop_sw_vsync() +{ + pthread_mutex_lock(&vsync_mutex); + if (!vsync_loop_active) { + pthread_mutex_unlock(&vsync_mutex); + return; + } + vsync_loop_active = false; + pthread_mutex_unlock(&vsync_mutex); + pthread_cond_signal(&vsync_cond); +} diff --git a/hwc/sw_vsync.h b/hwc/sw_vsync.h new file mode 100644 index 0000000..bb06165 --- /dev/null +++ b/hwc/sw_vsync.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) Texas Instruments - http://www.ti.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __SWVSYNC_H__ +#define __SWVSYNC_H__ + +bool use_sw_vsync(); +void init_sw_vsync(omap_hwc_device_t *hwc_dev); +void start_sw_vsync(); +void stop_sw_vsync(); + +#endif diff --git a/include/gralloc/ti_handle_wrapper.h b/include/gralloc/ti_handle_wrapper.h new file mode 100644 index 0000000..9a4189f --- /dev/null +++ b/include/gralloc/ti_handle_wrapper.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) Texas Instruments - http://www.ti.com/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _TI_HANDLE_WRAPPER_H_ +#define _TI_HANDLE_WRAPPER_H_ + +/* + * Provide wrapper api for getting fields from gralloc + * handles + */ +#define OMAP_LEGACY_HANDLE /* For now enable legacy handle by default */ +#ifdef OMAP_LEGACY_HANDLE + +#include "hal_public.h" +typedef IMG_native_handle_t ti_hndl_t; + +#define HND_W(h) h->iWidth +#define HND_H(h) h->iHeight +#define HND_FMT(h) h->iFormat + +/* + * Return total number of ion fd entries in the handle. + * + * Legacy handle does not support ion fds, so will return 0, use this test + * to determine whether to get pvr fds instead. + */ +#define GET_ION_FD_COUNT(h) 0 + +/* + * Return ion fd at index 'n'. + * + * Legacy handle does not support ion fds. + */ +#define GET_ION_FD(h, n) -1 + +/* + * Return pvr fd + */ +#define GET_PVR_FD(h) h->fd[0] + +#else + +#include "gralloc/gralloc_ti_handle.h" +#include "gralloc/hal_gpu_public.h" + +typedef gralloc_ti_handle ti_hndl_t; + +#define HND_W(h) h->width +#define HND_H(h) h->height +#define HND_FMT(h) h->format + +/* + * Return total number of ion fd entries in the handle. + */ +#define GET_ION_FD_COUNT(h) ti_gralloc_handle_num_of_planes(h) + +/* + * Return ion fd at index 'n'. + * + * When iterating through the fds, an fd with value < 0 indicates the start + * of the unused fd entries. + */ +#define GET_ION_FD(h, n) h->export_fds[n] + +/* + * Return pvr fd + */ +#define GET_PVR_FD(h) h->gpu_sync_fd + +#endif + +#endif /* _TI_HANDLE_WRAPPER_H_ */ |