diff options
author | Marissa Wall <marissaw@google.com> | 2016-09-02 09:51:19 -0700 |
---|---|---|
committer | Marissa Wall <marissaw@google.com> | 2017-03-02 12:35:07 -0800 |
commit | 9b0d80b6b4bc520a61af6f0e4cafc206660d9709 (patch) | |
tree | 7db9a8c2dd02aae524b039756b10e661868c7fa9 | |
parent | df4e35671b2475b8aa90e1047e48012f76802421 (diff) | |
download | flounder-9b0d80b6b4bc520a61af6f0e4cafc206660d9709.tar.gz |
hwc2: add hardware window support
Add support for assigning client target/layers to hardware windows. The windows
have different features that they can support.
Test: Add "TARGET_USES_HWC2 := true" to BoardConfig.mk.
Recompile.
Run testcases: https://android-review.googlesource.com/#/q/project:
platform/frameworks/native+branch:master+topic:test-hwc2
Change-Id: Id578790221c4007e0b0996d605df9de2c06543db
-rw-r--r-- | hwc2/Android.mk | 5 | ||||
-rw-r--r-- | hwc2/hwc2.h | 147 | ||||
-rw-r--r-- | hwc2/hwc2_buffer.cpp | 92 | ||||
-rw-r--r-- | hwc2/hwc2_display.cpp | 38 | ||||
-rw-r--r-- | hwc2/hwc2_gralloc.cpp | 93 | ||||
-rw-r--r-- | hwc2/hwc2_layer.cpp | 70 | ||||
-rw-r--r-- | hwc2/hwc2_window.cpp | 160 | ||||
-rw-r--r-- | hwc2/include/tegra_adf.h | 127 | ||||
-rw-r--r-- | hwc2/original-kernel-headers/tegra_adf.h | 125 |
9 files changed, 855 insertions, 2 deletions
diff --git a/hwc2/Android.mk b/hwc2/Android.mk index 8697126..b0a33cd 100644 --- a/hwc2/Android.mk +++ b/hwc2/Android.mk @@ -46,7 +46,10 @@ LOCAL_SRC_FILES := \ hwc2_callback.cpp \ hwc2_layer.cpp \ hwc2_buffer.cpp \ - hwc2_gralloc.cpp + hwc2_gralloc.cpp \ + hwc2_window.cpp + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include LOCAL_MODLE_TAGS := optional diff --git a/hwc2/hwc2.h b/hwc2/hwc2.h index 423f589..3ef4cef 100644 --- a/hwc2/hwc2.h +++ b/hwc2/hwc2.h @@ -21,18 +21,64 @@ #include <unordered_map> #include <queue> +#include <array> #include <mutex> #include <string> #include <adf/adf.h> #include <adfhwc/adfhwc.h> +#define HWC2_WINDOW_COUNT 4 + +#define HWC2_WINDOW_MIN_SOURCE_CROP_WIDTH 1.0 +#define HWC2_WINDOW_MIN_SOURCE_CROP_HEIGHT 1.0 +#define HWC2_WINDOW_MIN_DISPLAY_FRAME_WIDTH 4 +#define HWC2_WINDOW_MIN_DISPLAY_FRAME_HEIGHT 4 +#define HWC2_WINDOW_MIN_DISPLAY_FRAME_SCALE 0.5 + +#define HWC2_WINDOW_MAX_ROT_SRC_HEIGHT 2560 +#define HWC2_WINDOW_MAX_ROT_SRC_HEIGHT_NO_SCALE 3600 + +#define HWC2_WINDOW_CAP_YUV 0x001 +#define HWC2_WINDOW_CAP_SCALE 0x002 +#define HWC2_WINDOW_CAP_FLIP 0x004 +#define HWC2_WINDOW_CAP_ROTATE_PACKED 0x008 +#define HWC2_WINDOW_CAP_ROTATE_PLANAR 0x010 +#define HWC2_WINDOW_CAP_PITCH 0x020 +#define HWC2_WINDOW_CAP_TILED 0x040 +#define HWC2_WINDOW_CAP_BLOCK_LINEAR 0x080 + +#define HWC2_WINDOW_CAP_LAYOUTS (HWC2_WINDOW_CAP_PITCH \ + | HWC2_WINDOW_CAP_TILED \ + | HWC2_WINDOW_CAP_BLOCK_LINEAR) + +#define HWC2_WINDOW_CAP_COMMON (HWC2_WINDOW_CAP_YUV \ + | HWC2_WINDOW_CAP_SCALE \ + | HWC2_WINDOW_CAP_FLIP \ + | HWC2_WINDOW_CAP_ROTATE_PACKED \ + | HWC2_WINDOW_CAP_PITCH \ + | HWC2_WINDOW_CAP_TILED \ + | HWC2_WINDOW_CAP_BLOCK_LINEAR) + +static const std::array<uint32_t, HWC2_WINDOW_COUNT> window_capabilities = {{ + HWC2_WINDOW_CAP_COMMON | HWC2_WINDOW_CAP_ROTATE_PLANAR, + HWC2_WINDOW_CAP_COMMON, + HWC2_WINDOW_CAP_COMMON, + HWC2_WINDOW_CAP_PITCH +}}; + class hwc2_gralloc { public: /* hwc2_gralloc follows the singleton design pattern */ static const hwc2_gralloc &get_instance(); - bool is_valid(buffer_handle_t handle) const; + bool is_valid(buffer_handle_t handle) const; + bool is_stereo(buffer_handle_t handle) const; + bool is_yuv(buffer_handle_t handle) const; + int get_format(buffer_handle_t handle) const; + void get_surfaces(buffer_handle_t handle, const void **surf, + size_t *surf_cnt) const; + int32_t get_layout(const void *surf, uint32_t surf_idx) const; private: hwc2_gralloc(); @@ -42,6 +88,23 @@ private: * buffer is valid */ bool (*nvgr_is_valid)(buffer_handle_t handle); + /* The address of the nvgr_is_stereo symbol. This NVIDIA function checks if + * a buffer is stereo */ + bool (*nvgr_is_stereo)(buffer_handle_t handle); + + /* The address of the nvgr_is_yuv symbol. This NVIDIA function checks if a + * buffer is yuv */ + bool (*nvgr_is_yuv)(buffer_handle_t handle); + + /* The address of the nvgr_get_format symbol. This NVIDIA function returns + * the format of a buffer */ + int (*nvgr_get_format)(buffer_handle_t handle); + + /* The address of the nvgr_get_surfaces symbol. This NVIDIA function returns + * the surfaces associated with a buffer handle */ + void (*nvgr_get_surfaces)(buffer_handle_t handle, const void **surf, + size_t *surf_cnt); + /* A symbol table handle to the NVIDIA gralloc .so file. */ void *nvgr; }; @@ -53,6 +116,22 @@ public: void close_acquire_fence(); + /* Get properties */ + buffer_handle_t get_buffer_handle() const { return handle; } + hwc_transform_t get_transform() const { return transform; } + uint32_t get_adf_buffer_format() const; + uint32_t get_layout() const; + int get_display_frame_width() const; + int get_display_frame_height() const; + float get_source_crop_width() const; + float get_source_crop_height() const; + float get_scale_width() const; + float get_scale_height() const; + void get_surfaces(const void **surf, size_t *surf_cnt) const; + bool is_source_crop_int_aligned() const; + bool is_stereo() const; + bool is_yuv() const; + /* Set properties */ hwc2_error_t set_buffer(buffer_handle_t handle, int32_t acquire_fence); hwc2_error_t set_dataspace(android_dataspace_t dataspace); @@ -163,6 +242,20 @@ public: /* Get properties */ hwc2_layer_t get_id() const { return id; } hwc2_composition_t get_comp_type() const { return comp_type; } + buffer_handle_t get_buffer_handle() const; + hwc_transform_t get_transform() const; + uint32_t get_adf_buffer_format() const; + uint32_t get_layout() const; + int get_display_frame_width() const; + int get_display_frame_height() const; + float get_source_crop_width() const; + float get_source_crop_height() const; + float get_scale_width() const; + float get_scale_height() const; + void get_surfaces(const void **surf, size_t *surf_cnt) const; + bool is_source_crop_int_aligned() const; + bool is_stereo() const; + bool is_yuv() const; /* Set properties */ hwc2_error_t set_comp_type(hwc2_composition_t comp_type); @@ -194,6 +287,49 @@ private: static uint64_t layer_cnt; }; +class hwc2_window { +public: + hwc2_window(); + + void clear(); + hwc2_error_t assign_client_target(uint32_t z_order); + hwc2_error_t assign_layer(uint32_t z_order, const hwc2_layer &lyr); + + bool is_empty() const; + bool contains_client_target() const; + bool contains_layer() const; + + uint32_t get_z_order() const { return z_order; } + hwc2_layer_t get_layer() const { return lyr_id; } + + bool has_layer_requirements(const hwc2_layer &lyr) const; + bool has_requirements(uint32_t required_capabilities) const; + void set_capabilities(uint32_t capabilities); + + static bool is_supported(const hwc2_layer &lyr); + +private: + /* Each window can contain the client target, a layer or nothing */ + enum hwc2_window_content_t { + HWC2_WINDOW_CONTENT_EMPTY, + HWC2_WINDOW_CONTENT_CLIENT_TARGET, + HWC2_WINDOW_CONTENT_LAYER + } content; + + /* If the content is not HWC2_WINDOW_EMPTY, the z_order corresponds to the + * display controller z order. The display controller z order is the reverse + * of the SurfaceFlinger z order. In the display controller z order, a + * window with lower z order occludes a window with higher z order */ + uint32_t z_order; + + /* If the content is HWC2_WINDOW_LAYER, lyr_id is the layer it contains */ + hwc2_layer_t lyr_id; + + /* The capabilities the underlying hardware window can support such as + * rotation, scaling, flipping, yuv, and surface layouts */ + uint32_t capabilities; +}; + class hwc2_display { public: hwc2_display(hwc2_display_t id, int adf_intf_fd, @@ -216,6 +352,12 @@ public: hwc2_error_t set_power_mode(hwc2_power_mode_t mode); hwc2_error_t get_doze_support(int32_t *out_support) const; + /* Window functions */ + void init_windows(); + void clear_windows(); + hwc2_error_t assign_client_target_window(uint32_t z_order); + hwc2_error_t assign_layer_window(uint32_t z_order, hwc2_layer_t lyr_id); + /* Config functions */ int retrieve_display_configs(struct adf_hwc_helper *adf_helper); hwc2_error_t get_display_attribute(hwc2_config_t config, @@ -270,6 +412,9 @@ private: /* Physical or virtual */ hwc2_display_type_t type; + /* The display windows */ + std::array<hwc2_window, HWC2_WINDOW_COUNT> windows; + /* The layers currently in use */ std::unordered_map<hwc2_layer_t, hwc2_layer> layers; diff --git a/hwc2/hwc2_buffer.cpp b/hwc2/hwc2_buffer.cpp index 2344eb4..56b8115 100644 --- a/hwc2/hwc2_buffer.cpp +++ b/hwc2/hwc2_buffer.cpp @@ -44,6 +44,98 @@ void hwc2_buffer::close_acquire_fence() } } +uint32_t hwc2_buffer::get_adf_buffer_format() const +{ + if (!handle) + return 0; + + return hwc2_gralloc::get_instance().get_format(handle); +} + +uint32_t hwc2_buffer::get_layout() const +{ + const hwc2_gralloc &gralloc = hwc2_gralloc::get_instance(); + const void *surf; + size_t surf_cnt; + + if (!handle) + return 0; + + gralloc.get_surfaces(handle, &surf, &surf_cnt); + + return gralloc.get_layout(surf, 0); +} + +int hwc2_buffer::get_display_frame_width() const +{ + return display_frame.right - display_frame.left; +} + +int hwc2_buffer::get_display_frame_height() const +{ + return display_frame.bottom - display_frame.top; +} + +float hwc2_buffer::get_source_crop_width() const +{ + return source_crop.right - source_crop.left; +} + +float hwc2_buffer::get_source_crop_height() const +{ + return source_crop.bottom - source_crop.top; +} + +float hwc2_buffer::get_scale_width() const +{ + float source_crop_width = get_source_crop_width(); + if (source_crop_width == 0) + return -1.0; + + return get_display_frame_width() / source_crop_width; +} + +float hwc2_buffer::get_scale_height() const +{ + float source_crop_height = get_source_crop_height(); + if (source_crop_height == 0) + return -1.0; + + return get_display_frame_height() / source_crop_height; +} + +void hwc2_buffer::get_surfaces(const void **surf, size_t *surf_cnt) const +{ + if (!handle) + *surf_cnt = 0; + else + hwc2_gralloc::get_instance().get_surfaces(handle, surf, surf_cnt); +} + +bool hwc2_buffer::is_source_crop_int_aligned() const +{ + return (source_crop.left == ceil(source_crop.left) + && source_crop.top == ceil(source_crop.top) + && source_crop.right == ceil(source_crop.right) + && source_crop.bottom == ceil(source_crop.bottom)); +} + +bool hwc2_buffer::is_stereo() const +{ + if (!handle) + return false; + + return hwc2_gralloc::get_instance().is_stereo(handle); +} + +bool hwc2_buffer::is_yuv() const +{ + if (!handle) + return false; + + return hwc2_gralloc::get_instance().is_yuv(handle); +} + hwc2_error_t hwc2_buffer::set_buffer(buffer_handle_t handle, int32_t acquire_fence) { diff --git a/hwc2/hwc2_display.cpp b/hwc2/hwc2_display.cpp index 983bba7..a874aba 100644 --- a/hwc2/hwc2_display.cpp +++ b/hwc2/hwc2_display.cpp @@ -31,6 +31,7 @@ hwc2_display::hwc2_display(hwc2_display_t id, int adf_intf_fd, name(), connection(connection), type(type), + windows(), layers(), vsync_enabled(HWC2_VSYNC_DISABLE), configs(), @@ -40,6 +41,7 @@ hwc2_display::hwc2_display(hwc2_display_t id, int adf_intf_fd, adf_dev(adf_dev) { init_name(); + init_windows(); } hwc2_display::~hwc2_display() @@ -126,6 +128,42 @@ hwc2_error_t hwc2_display::set_vsync_enabled(hwc2_vsync_t enabled) return HWC2_ERROR_NONE; } +void hwc2_display::init_windows() +{ + for (auto it = windows.begin(); it != windows.end(); it++) + it->set_capabilities(window_capabilities[it - windows.begin()]); +} + +void hwc2_display::clear_windows() +{ + for (auto &window: windows) + window.clear(); +} + +hwc2_error_t hwc2_display::assign_client_target_window(uint32_t z_order) +{ + for (auto &window: windows) + if (window.assign_client_target(z_order) == HWC2_ERROR_NONE) + return HWC2_ERROR_NONE; + + return HWC2_ERROR_NO_RESOURCES; +} + +hwc2_error_t hwc2_display::assign_layer_window(uint32_t z_order, + hwc2_layer_t lyr_id) +{ + auto& lyr = layers.find(lyr_id)->second; + + if (!hwc2_window::is_supported(lyr)) + return HWC2_ERROR_UNSUPPORTED; + + for (auto &window: windows) + if (window.assign_layer(z_order, lyr) == HWC2_ERROR_NONE) + return HWC2_ERROR_NONE; + + return HWC2_ERROR_NO_RESOURCES; +} + int hwc2_display::retrieve_display_configs(struct adf_hwc_helper *adf_helper) { size_t num_configs = 0; diff --git a/hwc2/hwc2_gralloc.cpp b/hwc2/hwc2_gralloc.cpp index 9301b3d..0b82b45 100644 --- a/hwc2/hwc2_gralloc.cpp +++ b/hwc2/hwc2_gralloc.cpp @@ -16,9 +16,32 @@ #include <cutils/log.h> #include <dlfcn.h> +#include <tegra_adf.h> #include "hwc2.h" +#define NVGR_PIXEL_FORMAT_YUV420 0x100 +#define NVGR_PIXEL_FORMAT_YUV422 0x101 +#define NVGR_PIXEL_FORMAT_YUV422R 0x102 +#define NVGR_PIXEL_FORMAT_UYVY 0x104 +#define NVGR_PIXEL_FORMAT_NV12 0x106 + +#define NVGR_SURFACE_LAYOUT_PITCH 1 +#define NVGR_SURFACE_LAYOUT_TILED 2 +#define NVGR_SURFACE_LAYOUT_BLOCK_LINEAR 3 + +#define NVGR_SURFACE_SIZE 56 + +#define NVGR_GET_SURFACE(surfaces, idx) \ + ((void*)((char *) surfaces + (idx * NVGR_SURFACE_SIZE))) + +/* The surface struct is defined in an NVIDIA binary. Accesses to the struct + * will be done using member offsets */ +#define NVGR_GET_STRUCT_MEMBER(ptr, member_type, member_offset) \ + (*((member_type *)((char *) ptr + member_offset))) + +#define NVGR_SURFACE_OFFSET_LAYOUT 12 + hwc2_gralloc::hwc2_gralloc() { nvgr = dlopen("gralloc.tegra132.so", RTLD_LOCAL | RTLD_LAZY); @@ -27,6 +50,20 @@ hwc2_gralloc::hwc2_gralloc() *(void **)(&nvgr_is_valid) = dlsym(nvgr, "nvgr_is_valid"); LOG_ALWAYS_FATAL_IF(!nvgr_is_valid, "failed to find nvgr_is_valid symbol"); + *(void **)(&nvgr_is_stereo) = dlsym(nvgr, "nvgr_is_stereo"); + LOG_ALWAYS_FATAL_IF(!nvgr_is_stereo, "failed to find nvgr_is_stereo" + " symbol"); + + *(void **)(&nvgr_is_yuv) = dlsym(nvgr, "nvgr_is_yuv"); + LOG_ALWAYS_FATAL_IF(!nvgr_is_stereo, "failed to find nvgr_is_yuv symbol"); + + *(void **)(&nvgr_get_format) = dlsym(nvgr, "nvgr_get_format"); + LOG_ALWAYS_FATAL_IF(!nvgr_get_format, "failed to find nvgr_get_format" + " symbol"); + + *(void **)(&nvgr_get_surfaces) = dlsym(nvgr, "nvgr_get_surfaces"); + LOG_ALWAYS_FATAL_IF(!nvgr_get_surfaces, "failed to find nvgr_get_surfaces" + " symbol"); } hwc2_gralloc::~hwc2_gralloc() @@ -44,3 +81,59 @@ bool hwc2_gralloc::is_valid(buffer_handle_t handle) const { return nvgr_is_valid(handle); } + +bool hwc2_gralloc::is_stereo(buffer_handle_t handle) const +{ + return nvgr_is_stereo(handle); +} + +bool hwc2_gralloc::is_yuv(buffer_handle_t handle) const +{ + return nvgr_is_yuv(handle); +} + +int hwc2_gralloc::get_format(buffer_handle_t handle) const +{ + int format = nvgr_get_format(handle); + + switch (format) { + case HAL_PIXEL_FORMAT_RGB_565: + return DRM_FORMAT_BGR565; + case NVGR_PIXEL_FORMAT_YUV420: + return DRM_FORMAT_YUV420; + case NVGR_PIXEL_FORMAT_YUV422: + return DRM_FORMAT_YUV422; + case NVGR_PIXEL_FORMAT_YUV422R: + return TEGRA_ADF_FORMAT_YCbCr422R; + case NVGR_PIXEL_FORMAT_UYVY: + return DRM_FORMAT_UYVY; + case NVGR_PIXEL_FORMAT_NV12: + return DRM_FORMAT_NV12; + default: + return adf_fourcc_for_hal_pixel_format(format); + } +} + +void hwc2_gralloc::get_surfaces(buffer_handle_t handle, + const void **surf, size_t *surf_cnt) const +{ + nvgr_get_surfaces(handle, surf, surf_cnt); +} + +int32_t hwc2_gralloc::get_layout(const void *surf, uint32_t surf_idx) const +{ + uint32_t layout = NVGR_GET_STRUCT_MEMBER(NVGR_GET_SURFACE(surf, surf_idx), + uint32_t, NVGR_SURFACE_OFFSET_LAYOUT); + + switch (layout) { + case NVGR_SURFACE_LAYOUT_PITCH: + return HWC2_WINDOW_CAP_PITCH; + case NVGR_SURFACE_LAYOUT_TILED: + return HWC2_WINDOW_CAP_TILED; + case NVGR_SURFACE_LAYOUT_BLOCK_LINEAR: + return HWC2_WINDOW_CAP_BLOCK_LINEAR; + default: + ALOGE("Unrecognized layout"); + return -1; + } +} diff --git a/hwc2/hwc2_layer.cpp b/hwc2/hwc2_layer.cpp index 125f28f..4da2919 100644 --- a/hwc2/hwc2_layer.cpp +++ b/hwc2/hwc2_layer.cpp @@ -26,6 +26,76 @@ hwc2_layer::hwc2_layer(hwc2_layer_t id) buffer(), comp_type(HWC2_COMPOSITION_INVALID) { } +buffer_handle_t hwc2_layer::get_buffer_handle() const +{ + return buffer.get_buffer_handle(); +} + +hwc_transform_t hwc2_layer::get_transform() const +{ + return buffer.get_transform(); +} + +uint32_t hwc2_layer::get_adf_buffer_format() const +{ + return buffer.get_adf_buffer_format(); +} + +uint32_t hwc2_layer::get_layout() const +{ + return buffer.get_layout(); +} + +int hwc2_layer::get_display_frame_width() const +{ + return buffer.get_display_frame_width(); +} + +int hwc2_layer::get_display_frame_height() const +{ + return buffer.get_display_frame_height(); +} + +float hwc2_layer::get_source_crop_width() const +{ + return buffer.get_source_crop_width(); +} + +float hwc2_layer::get_source_crop_height() const +{ + return buffer.get_source_crop_height(); +} + +float hwc2_layer::get_scale_width() const +{ + return buffer.get_scale_width(); +} + +float hwc2_layer::get_scale_height() const +{ + return buffer.get_scale_height(); +} + +void hwc2_layer::get_surfaces(const void **surf, size_t *surf_cnt) const +{ + buffer.get_surfaces(surf, surf_cnt); +} + +bool hwc2_layer::is_source_crop_int_aligned() const +{ + return buffer.is_source_crop_int_aligned(); +} + +bool hwc2_layer::is_stereo() const +{ + return buffer.is_stereo(); +} + +bool hwc2_layer::is_yuv() const +{ + return buffer.is_yuv(); +} + hwc2_error_t hwc2_layer::set_comp_type(hwc2_composition_t comp_type) { hwc2_error_t ret = HWC2_ERROR_NONE; diff --git a/hwc2/hwc2_window.cpp b/hwc2/hwc2_window.cpp new file mode 100644 index 0000000..ca2f7f6 --- /dev/null +++ b/hwc2/hwc2_window.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * 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 <cassert> + +#include "hwc2.h" + +hwc2_window::hwc2_window() + : content(HWC2_WINDOW_CONTENT_EMPTY), + z_order(0), + lyr_id(0) { } + +void hwc2_window::clear() +{ + content = HWC2_WINDOW_CONTENT_EMPTY; +} + +hwc2_error_t hwc2_window::assign_client_target(uint32_t z_order) +{ + /* The client target will never rotate, scale or flip. Its buffer layout + * could be changed before present display, so the window must support all + * layouts. */ + if (!is_empty() || !has_requirements(HWC2_WINDOW_CAP_LAYOUTS)) + return HWC2_ERROR_UNSUPPORTED; + + content = HWC2_WINDOW_CONTENT_CLIENT_TARGET; + this->z_order = z_order; + + return HWC2_ERROR_NONE; +} + +hwc2_error_t hwc2_window::assign_layer(uint32_t z_order, const hwc2_layer &lyr) +{ + if (!is_empty() || !has_layer_requirements(lyr)) + return HWC2_ERROR_UNSUPPORTED; + + content = HWC2_WINDOW_CONTENT_LAYER; + this->z_order = z_order; + this->lyr_id = lyr.get_id(); + + return HWC2_ERROR_NONE; +} + +bool hwc2_window::is_empty() const +{ + return content == HWC2_WINDOW_CONTENT_EMPTY; +} + +bool hwc2_window::contains_client_target() const +{ + return content == HWC2_WINDOW_CONTENT_CLIENT_TARGET; +} + +bool hwc2_window::contains_layer() const +{ + return content == HWC2_WINDOW_CONTENT_LAYER; +} + +bool hwc2_window::has_layer_requirements(const hwc2_layer &lyr) const +{ + hwc_transform_t transform = lyr.get_transform(); + uint32_t reqs = 0; + int32_t layout; + + layout = lyr.get_layout(); + if (layout < 0) + return false; + + reqs |= layout; + + if (transform & HWC_TRANSFORM_ROT_90) { + const void *surf; + size_t surf_cnt; + lyr.get_surfaces(&surf, &surf_cnt); + + if (surf_cnt > 1) + reqs |= HWC2_WINDOW_CAP_ROTATE_PLANAR; + else + reqs |= HWC2_WINDOW_CAP_ROTATE_PACKED; + } + + if (transform & (HWC_TRANSFORM_FLIP_H | HWC_TRANSFORM_FLIP_V)) + reqs |= HWC2_WINDOW_CAP_FLIP; + + if (lyr.get_scale_width() != 1 || lyr.get_scale_height() != 1) + reqs |= HWC2_WINDOW_CAP_SCALE; + + if (lyr.is_yuv()) + reqs |= HWC2_WINDOW_CAP_YUV; + + return has_requirements(reqs); +} + +bool hwc2_window::has_requirements(uint32_t requirements) const +{ + return (requirements & capabilities) == requirements; +} + +void hwc2_window::set_capabilities(uint32_t capabilities) +{ + this->capabilities = capabilities; +} + +bool hwc2_window::is_supported(const hwc2_layer &lyr) +{ + float source_crop_height = lyr.get_source_crop_height(); + float scale_width = lyr.get_scale_width(); + float scale_height = lyr.get_scale_height(); + + if (!lyr.get_buffer_handle()) + return false; + + if (!lyr.get_adf_buffer_format()) + return false; + + if (lyr.is_stereo()) + return false; + + if (lyr.get_display_frame_width() < HWC2_WINDOW_MIN_DISPLAY_FRAME_WIDTH + || lyr.get_display_frame_height() < HWC2_WINDOW_MIN_DISPLAY_FRAME_HEIGHT) + return false; + + if (lyr.get_source_crop_width() < HWC2_WINDOW_MIN_SOURCE_CROP_WIDTH + || source_crop_height < HWC2_WINDOW_MIN_SOURCE_CROP_HEIGHT) + return false; + + if (scale_width < HWC2_WINDOW_MIN_DISPLAY_FRAME_SCALE + || scale_height < HWC2_WINDOW_MIN_DISPLAY_FRAME_SCALE) + return false; + + const void *surf; + size_t surf_cnt; + lyr.get_surfaces(&surf, &surf_cnt); + + if (lyr.get_transform() & HWC_TRANSFORM_ROT_90) { + if (surf_cnt == 1 && scale_width == 1 && scale_height == 1 + && source_crop_height > HWC2_WINDOW_MAX_ROT_SRC_HEIGHT_NO_SCALE) + return false; + else if (source_crop_height > HWC2_WINDOW_MAX_ROT_SRC_HEIGHT) + return false; + } + + if (!lyr.is_source_crop_int_aligned()) + return false; + + return true; +} diff --git a/hwc2/include/tegra_adf.h b/hwc2/include/tegra_adf.h new file mode 100644 index 0000000..52e4d17 --- /dev/null +++ b/hwc2/include/tegra_adf.h @@ -0,0 +1,127 @@ +/**************************************************************************** + **************************************************************************** + *** + *** This header was automatically generated from a Linux kernel header + *** of the same name, to make information necessary for userspace to + *** call into the kernel available to libc. It contains only constants, + *** structures, and macros generated from the original header, and thus, + *** contains no copyrightable information. + *** + *** To edit the content of this header, modify the corresponding + *** source file (e.g. under external/kernel-headers/original/) then + *** run bionic/libc/kernel/tools/update_all.py + *** + *** Any manual change here will be lost the next time this script will + *** be run. You've been warned! + *** + **************************************************************************** + ****************************************************************************/ +#ifndef _UAPI_VIDEO_TEGRA_ADF_H_ +#define _UAPI_VIDEO_TEGRA_ADF_H_ +#include <linux/types.h> +#include <video/adf.h> +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ +#include <drm/drm_fourcc.h> +#define TEGRA_ADF_FORMAT_P1 fourcc_code('P', '1', ' ', ' ') +#define TEGRA_ADF_FORMAT_P2 fourcc_code('P', '2', ' ', ' ') +#define TEGRA_ADF_FORMAT_P4 fourcc_code('P', '4', ' ', ' ') +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ +#define TEGRA_ADF_FORMAT_P8 fourcc_code('P', '8', ' ', ' ') +#define TEGRA_ADF_FORMAT_B6x2G6x2R6x2A8 fourcc_code('B', 'A', '6', '2') +#define TEGRA_ADF_FORMAT_R6x2G6x2B6x2A8 fourcc_code('R', 'A', '6', '2') +#define TEGRA_ADF_FORMAT_R6x2G6x2B6x2A8 fourcc_code('R', 'A', '6', '2') +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ +#define TEGRA_ADF_FORMAT_YCbCr422R fourcc_code('Y', 'U', '2', 'R') +enum tegra_adf_interface_type { + TEGRA_ADF_INTF_RGB = ADF_INTF_TYPE_DEVICE_CUSTOM, + TEGRA_ADF_INTF_LVDS = ADF_INTF_TYPE_DEVICE_CUSTOM + 1, +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ +}; +#define TEGRA_ADF_EVENT_BANDWIDTH_RENEGOTIATE ADF_EVENT_DEVICE_CUSTOM +struct tegra_adf_event_bandwidth { + struct adf_event base; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + __u32 total_bw; + __u32 avail_bw; + __u32 resvd_bw; +}; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ +#define TEGRA_ADF_CAPABILITIES_CURSOR_MODE (1 << 0) +#define TEGRA_ADF_CAPABILITIES_BLOCKLINEAR (1 << 1) +struct tegra_adf_capabilities { + __u32 caps; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + __u32 pad[3]; +}; +#define TEGRA_ADF_BLEND_NONE 0 +#define TEGRA_ADF_BLEND_PREMULT 1 +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ +#define TEGRA_ADF_BLEND_COVERAGE 2 +#define TEGRA_ADF_FLIP_FLAG_INVERT_H (1 << 0) +#define TEGRA_ADF_FLIP_FLAG_INVERT_V (1 << 1) +#define TEGRA_ADF_FLIP_FLAG_TILED (1 << 2) +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ +#define TEGRA_ADF_FLIP_FLAG_CURSOR (1 << 3) +#define TEGRA_ADF_FLIP_FLAG_GLOBAL_ALPHA (1 << 4) +#define TEGRA_ADF_FLIP_FLAG_BLOCKLINEAR (1 << 5) +#define TEGRA_ADF_FLIP_FLAG_SCAN_COLUMN (1 << 6) +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ +#define TEGRA_ADF_FLIP_FLAG_INTERLACE (1 << 7) +struct tegra_adf_flip_windowattr { + __s32 win_index; + __s32 buf_index; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + __u32 blend; + __u32 x; + __u32 y; + __u32 out_x; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + __u32 out_y; + __u32 out_w; + __u32 out_h; + __u32 z; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + __u32 swap_interval; + __s64 timestamp_ns; + __u32 flags; + __u8 global_alpha; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + __u8 block_height_log2; + __u8 pad1[2]; + __u32 offset2; + __u32 offset_u2; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + __u32 offset_v2; + __u32 pad2[1]; +}; +struct tegra_adf_flip { +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + __u8 win_num; + __u8 reserved1; + __u16 reserved2; + __u16 dirty_rect[4]; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + struct tegra_adf_flip_windowattr win[0]; +}; +struct tegra_adf_proposed_bw { + __u8 win_num; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + struct { + __u32 format; + __u32 w; + __u32 h; +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + struct tegra_adf_flip_windowattr attr; + } win[0]; +}; +#define TEGRA_ADF_SET_PROPOSED_BW _IOW(ADF_IOCTL_TYPE, ADF_IOCTL_NR_CUSTOM, struct tegra_adf_proposed_bw) +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ +enum { + TEGRA_DC_Y, + TEGRA_DC_U, + TEGRA_DC_V, +/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ + TEGRA_DC_NUM_PLANES, +}; +#endif + diff --git a/hwc2/original-kernel-headers/tegra_adf.h b/hwc2/original-kernel-headers/tegra_adf.h new file mode 100644 index 0000000..7313111 --- /dev/null +++ b/hwc2/original-kernel-headers/tegra_adf.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2013 Google, Inc. + * Copyright (c) 2014, NVIDIA CORPORATION, All rights reserved. + * + * modified from include/video/tegra_dc_ext.h + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _UAPI_VIDEO_TEGRA_ADF_H_ +#define _UAPI_VIDEO_TEGRA_ADF_H_ + +#include <linux/types.h> +#include <video/adf.h> +#include <drm/drm_fourcc.h> + +#define TEGRA_ADF_FORMAT_P1 fourcc_code('P', '1', ' ', ' ') +#define TEGRA_ADF_FORMAT_P2 fourcc_code('P', '2', ' ', ' ') +#define TEGRA_ADF_FORMAT_P4 fourcc_code('P', '4', ' ', ' ') +#define TEGRA_ADF_FORMAT_P8 fourcc_code('P', '8', ' ', ' ') +#define TEGRA_ADF_FORMAT_B6x2G6x2R6x2A8 fourcc_code('B', 'A', '6', '2') +#define TEGRA_ADF_FORMAT_R6x2G6x2B6x2A8 fourcc_code('R', 'A', '6', '2') +#define TEGRA_ADF_FORMAT_R6x2G6x2B6x2A8 fourcc_code('R', 'A', '6', '2') +#define TEGRA_ADF_FORMAT_YCbCr422R fourcc_code('Y', 'U', '2', 'R') + +enum tegra_adf_interface_type { + TEGRA_ADF_INTF_RGB = ADF_INTF_TYPE_DEVICE_CUSTOM, + TEGRA_ADF_INTF_LVDS = ADF_INTF_TYPE_DEVICE_CUSTOM + 1, +}; + +#define TEGRA_ADF_EVENT_BANDWIDTH_RENEGOTIATE ADF_EVENT_DEVICE_CUSTOM +struct tegra_adf_event_bandwidth { + struct adf_event base; + __u32 total_bw; + __u32 avail_bw; + __u32 resvd_bw; +}; + +#define TEGRA_ADF_CAPABILITIES_CURSOR_MODE (1 << 0) +#define TEGRA_ADF_CAPABILITIES_BLOCKLINEAR (1 << 1) +struct tegra_adf_capabilities { + __u32 caps; + /* Leave some wiggle room for future expansion */ + __u32 pad[3]; +}; + +#define TEGRA_ADF_BLEND_NONE 0 +#define TEGRA_ADF_BLEND_PREMULT 1 +#define TEGRA_ADF_BLEND_COVERAGE 2 + +#define TEGRA_ADF_FLIP_FLAG_INVERT_H (1 << 0) +#define TEGRA_ADF_FLIP_FLAG_INVERT_V (1 << 1) +#define TEGRA_ADF_FLIP_FLAG_TILED (1 << 2) +#define TEGRA_ADF_FLIP_FLAG_CURSOR (1 << 3) +#define TEGRA_ADF_FLIP_FLAG_GLOBAL_ALPHA (1 << 4) +#define TEGRA_ADF_FLIP_FLAG_BLOCKLINEAR (1 << 5) +#define TEGRA_ADF_FLIP_FLAG_SCAN_COLUMN (1 << 6) +#define TEGRA_ADF_FLIP_FLAG_INTERLACE (1 << 7) + +struct tegra_adf_flip_windowattr { + __s32 win_index; + __s32 buf_index; + __u32 blend; + /* + * x and y are fixed-point: 20 bits of integer (MSB) and 12 bits of + * fractional (LSB) + */ + __u32 x; + __u32 y; + __u32 out_x; + __u32 out_y; + __u32 out_w; + __u32 out_h; + __u32 z; + __u32 swap_interval; + __s64 timestamp_ns; + __u32 flags; + __u8 global_alpha; /* requires TEGRA_ADF_FLIP_FLAG_GLOBAL_ALPHA */ + /* log2(blockheight) for blocklinear format */ + __u8 block_height_log2; + __u8 pad1[2]; + __u32 offset2; + __u32 offset_u2; + __u32 offset_v2; + /* Leave some wiggle room for future expansion */ + __u32 pad2[1]; +}; + +struct tegra_adf_flip { + __u8 win_num; + __u8 reserved1; /* unused - must be 0 */ + __u16 reserved2; /* unused - must be 0 */ + __u16 dirty_rect[4]; /* x,y,w,h for partial screen update. 0 ignores */ + struct tegra_adf_flip_windowattr win[0]; +}; + +struct tegra_adf_proposed_bw { + __u8 win_num; + struct { + __u32 format; + __u32 w; + __u32 h; + struct tegra_adf_flip_windowattr attr; + } win[0]; +}; + +#define TEGRA_ADF_SET_PROPOSED_BW \ + _IOW(ADF_IOCTL_TYPE, ADF_IOCTL_NR_CUSTOM, struct tegra_adf_proposed_bw) + +enum { + TEGRA_DC_Y, + TEGRA_DC_U, + TEGRA_DC_V, + TEGRA_DC_NUM_PLANES, +}; + +#endif /* _UAPI_VIDEO_TEGRA_ADF_H_ */ |