diff options
Diffstat (limited to 'hwc')
-rw-r--r-- | hwc/Android.mk | 2 | ||||
-rw-r--r-- | hwc/display.c | 182 | ||||
-rw-r--r-- | hwc/display.h | 48 | ||||
-rw-r--r-- | hwc/hwc.c | 25 | ||||
-rw-r--r-- | hwc/hwc_dev.h | 2 |
5 files changed, 252 insertions, 7 deletions
diff --git a/hwc/Android.mk b/hwc/Android.mk index dd83714..e8e59f0 100644 --- a/hwc/Android.mk +++ b/hwc/Android.mk @@ -8,7 +8,7 @@ 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_ti -LOCAL_SRC_FILES := hwc.c rgz_2d.c dock_image.c sw_vsync.c +LOCAL_SRC_FILES := hwc.c rgz_2d.c dock_image.c sw_vsync.c display.c LOCAL_STATIC_LIBRARIES := libpng LOCAL_MODULE_TAGS := optional diff --git a/hwc/display.c b/hwc/display.c new file mode 100644 index 0000000..bd59813 --- /dev/null +++ b/hwc/display.c @@ -0,0 +1,182 @@ +/* + * 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 <cutils/log.h> + +#include <video/dsscomp.h> + +#include "hwc_dev.h" +#include "display.h" + +#define PRIMARY_DISPLAY_CONFIGS 1 +#define PRIMARY_DISPLAY_FPS 60 +#define PRIMARY_DISPLAY_DEFAULT_DPI 150 +#define MAX_DISPLAY_ID (MAX_DISPLAYS - 1) +#define INCH_TO_MM 25.4f + +static void free_display(display_t *display) +{ + if (display) { + if (display->configs) + free(display->configs); + + free(display); + } +} + +static int allocate_display(uint32_t max_configs, display_t **new_display) +{ + int err = 0; + + display_t *display = (display_t *)malloc(sizeof(*display)); + if (display == NULL) { + err = -ENOMEM; + goto err_out; + } + + memset(display, 0, sizeof(*display)); + + display->num_configs = max_configs; + size_t config_data_size = sizeof(*display->configs) * display->num_configs; + display->configs = (display_config_t *)malloc(config_data_size); + if (display->configs == NULL) { + err = -ENOMEM; + goto err_out; + } + + memset(display->configs, 0, config_data_size); + +err_out: + + if (err) { + ALOGE("Failed to allocate display (configs = %d)", max_configs); + free_display(display); + } else { + *new_display = display; + } + + return err; +} + +int init_primary_display(omap_hwc_device_t *hwc_dev) +{ + int ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_QUERY_DISPLAY, &hwc_dev->fb_dis); + if (ret) { + ALOGE("failed to get display info (%d): %m", errno); + return -errno; + } + + int err = allocate_display(PRIMARY_DISPLAY_CONFIGS, &hwc_dev->displays[HWC_DISPLAY_PRIMARY]); + if (err) + return err; + + display_config_t *config = &hwc_dev->displays[HWC_DISPLAY_PRIMARY]->configs[0]; + + config->xres = hwc_dev->fb_dis.timings.x_res; + config->yres = hwc_dev->fb_dis.timings.y_res; + config->fps = PRIMARY_DISPLAY_FPS; + + if (hwc_dev->fb_dis.width_in_mm && hwc_dev->fb_dis.height_in_mm) { + config->xdpi = (int)(config->xres * INCH_TO_MM) / hwc_dev->fb_dis.width_in_mm; + config->ydpi = (int)(config->yres * INCH_TO_MM) / hwc_dev->fb_dis.height_in_mm; + } else { + config->xdpi = PRIMARY_DISPLAY_DEFAULT_DPI; + config->ydpi = PRIMARY_DISPLAY_DEFAULT_DPI; + } + + return 0; +} + +int get_display_configs(omap_hwc_device_t *hwc_dev, int disp, uint32_t *configs, size_t *numConfigs) +{ + if (!numConfigs) + return -EINVAL; + + if (*numConfigs == 0) + return 0; + + if (!configs || disp < 0 || disp > MAX_DISPLAY_ID || !hwc_dev->displays[disp]) + return -EINVAL; + + display_t *display = hwc_dev->displays[disp]; + size_t num = display->num_configs; + uint32_t c; + + if (num > *numConfigs) + num = *numConfigs; + + for (c = 0; c < num; c++) + configs[c] = c; + + *numConfigs = num; + + return 0; +} + +int get_display_attributes(omap_hwc_device_t *hwc_dev, int disp, uint32_t cfg, const uint32_t *attributes, int32_t *values) +{ + if (!attributes || !values) + return 0; + + if (disp < 0 || disp > MAX_DISPLAY_ID || !hwc_dev->displays[disp]) + return -EINVAL; + + display_t *display = hwc_dev->displays[disp]; + + if (cfg >= display->num_configs) + return -EINVAL; + + const uint32_t* attribute = attributes; + int32_t* value = values; + display_config_t *config = &display->configs[cfg]; + + while (*attribute != HWC_DISPLAY_NO_ATTRIBUTE) { + switch (*attribute) { + case HWC_DISPLAY_VSYNC_PERIOD: + *value = 1000000000 / config->fps; + break; + case HWC_DISPLAY_WIDTH: + *value = config->xres; + break; + case HWC_DISPLAY_HEIGHT: + *value = config->yres; + break; + case HWC_DISPLAY_DPI_X: + *value = 1000 * config->xdpi; + break; + case HWC_DISPLAY_DPI_Y: + *value = 1000 * config->ydpi; + break; + } + + attribute++; + value++; + } + + return 0; +} + +void free_displays(omap_hwc_device_t *hwc_dev) +{ + int i; + for (i = 0; i < MAX_DISPLAYS; i++) + free_display(hwc_dev->displays[i]); +} diff --git a/hwc/display.h b/hwc/display.h new file mode 100644 index 0000000..f24fc41 --- /dev/null +++ b/hwc/display.h @@ -0,0 +1,48 @@ +/* + * 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 __DISPLAY__ +#define __DISPLAY__ + +#include <stdint.h> + +#define MAX_DISPLAYS 3 +#define MAX_DISPLAY_CONFIGS 32 + +struct display_config { + int xres; + int yres; + int fps; + int xdpi; + int ydpi; +}; +typedef struct display_config display_config_t; + +struct display { + uint32_t num_configs; + display_config_t *configs; + uint32_t active_config_ix; +}; +typedef struct display display_t; + +typedef struct omap_hwc_device omap_hwc_device_t; + +int init_primary_display(omap_hwc_device_t *hwc_dev); +int get_display_configs(omap_hwc_device_t *hwc_dev, int disp, uint32_t *configs, size_t *numConfigs); +int get_display_attributes(omap_hwc_device_t *hwc_dev, int disp, uint32_t config, const uint32_t *attributes, int32_t *values); +void free_displays(omap_hwc_device_t *hwc_dev); + +#endif @@ -44,6 +44,7 @@ #include <ion_ti/ion.h> #include "hwc_dev.h" +#include "display.h" #include "dock_image.h" #include "sw_vsync.h" @@ -844,7 +845,7 @@ static int set_best_hdmi_mode(omap_hwc_device_t *hwc_dev, uint32_t xres, uint32_ int dis_ix = hwc_dev->on_tv ? 0 : 1; struct _qdis { struct dsscomp_display_info dis; - struct dsscomp_videomode modedb[32]; + struct dsscomp_videomode modedb[MAX_DISPLAY_CONFIGS]; } d = { .dis = { .ix = dis_ix } }; omap_hwc_ext_t *ext = &hwc_dev->ext; @@ -2096,6 +2097,7 @@ static int hwc_device_close(hw_device_t* device) /* pthread will get killed when parent process exits */ pthread_mutex_destroy(&hwc_dev->lock); + free_displays(hwc_dev); free(hwc_dev); } @@ -2473,6 +2475,17 @@ static int hwc_blank(struct hwc_composer_device_1 *dev, int dpy, int blank) return 0; } +static int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp, uint32_t* configs, size_t* numConfigs) +{ + return get_display_configs((omap_hwc_device_t *)dev, disp, configs, numConfigs); +} + +static int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp, + uint32_t config, const uint32_t* attributes, int32_t* values) +{ + return get_display_attributes((omap_hwc_device_t *)dev, disp, config, attributes, values); +} + static int hwc_device_open(const hw_module_t* module, const char* name, hw_device_t** device) { omap_hwc_module_t *hwc_mod = (omap_hwc_module_t *)module; @@ -2517,6 +2530,8 @@ static int hwc_device_open(const hw_module_t* module, const char* name, hw_devic hwc_dev->base.blank = hwc_blank; hwc_dev->base.dump = hwc_dump; hwc_dev->base.registerProcs = hwc_registerProcs; + hwc_dev->base.getDisplayConfigs = hwc_getDisplayConfigs; + hwc_dev->base.getDisplayAttributes = hwc_getDisplayAttributes; hwc_dev->base.query = hwc_query; hwc_dev->fb_dev = hwc_mod->fb_dev; @@ -2554,12 +2569,9 @@ static int hwc_device_open(const hw_module_t* module, const char* name, hw_devic goto done; } - ret = ioctl(hwc_dev->dsscomp_fd, DSSCIOC_QUERY_DISPLAY, &hwc_dev->fb_dis); - if (ret) { - ALOGE("failed to get display info (%d): %m", errno); - err = -errno; + err = init_primary_display(hwc_dev); + if (err) goto done; - } hwc_dev->ion_fd = ion_open(); if (hwc_dev->ion_fd < 0) { @@ -2693,6 +2705,7 @@ done: close(hwc_dev->fb_fd); pthread_mutex_destroy(&hwc_dev->lock); free(hwc_dev->buffers); + free_displays(hwc_dev); free(hwc_dev); } diff --git a/hwc/hwc_dev.h b/hwc/hwc_dev.h index 9acc9aa..471a577 100644 --- a/hwc/hwc_dev.h +++ b/hwc/hwc_dev.h @@ -31,6 +31,7 @@ #include "hal_public.h" #include "rgz_2d.h" +#include "display.h" struct ext_transform { uint8_t rotation : 3; /* 90-degree clockwise rotations */ @@ -172,6 +173,7 @@ struct omap_hwc_device { struct ion_handle *ion_handles[2]; bool use_sw_vsync; + display_t *displays[MAX_DISPLAYS]; }; typedef struct omap_hwc_device omap_hwc_device_t; |