| /* |
| * Copyright 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 "impl/vr_hwc.h" |
| |
| #include "android-base/stringprintf.h" |
| #include <cutils/properties.h> |
| #include <private/dvr/display_client.h> |
| #include <ui/Fence.h> |
| |
| #include <mutex> |
| |
| #include "vr_composer_client.h" |
| |
| using namespace android::hardware::graphics::common::V1_0; |
| using namespace android::hardware::graphics::composer::V2_1; |
| |
| using android::base::StringPrintf; |
| using android::hardware::hidl_handle; |
| using android::hardware::hidl_string; |
| using android::hardware::hidl_vec; |
| using android::hardware::Return; |
| using android::hardware::Void; |
| |
| namespace android { |
| namespace dvr { |
| namespace { |
| |
| using android::hardware::graphics::common::V1_0::PixelFormat; |
| |
| const Display kDefaultDisplayId = 1; |
| const Config kDefaultConfigId = 1; |
| |
| sp<GraphicBuffer> CreateGraphicBuffer( |
| const native_handle_t* handle, |
| const IVrComposerClient::BufferMetadata& metadata) { |
| sp<GraphicBuffer> buffer = new GraphicBuffer( |
| handle, GraphicBuffer::CLONE_HANDLE, metadata.width, metadata.height, |
| static_cast<int32_t>(metadata.format), metadata.layerCount, |
| metadata.usage, metadata.stride); |
| if (buffer->initCheck() != OK) { |
| ALOGE("Failed to create graphic buffer"); |
| return nullptr; |
| } |
| |
| return buffer; |
| } |
| |
| void GetPrimaryDisplaySize(int32_t* width, int32_t* height) { |
| *width = 1080; |
| *height = 1920; |
| |
| int error = 0; |
| auto display_client = display::DisplayClient::Create(&error); |
| if (!display_client) { |
| ALOGE("Could not connect to display service : %s(%d)", strerror(error), |
| error); |
| return; |
| } |
| |
| auto status = display_client->GetDisplayMetrics(); |
| if (!status) { |
| ALOGE("Could not get display metrics from display service : %s(%d)", |
| status.GetErrorMessage().c_str(), status.error()); |
| return; |
| } |
| |
| *width = status.get().display_width; |
| *height = status.get().display_height; |
| } |
| |
| } // namespace |
| |
| HwcDisplay::HwcDisplay(int32_t width, int32_t height) |
| : width_(width), height_(height) {} |
| |
| HwcDisplay::~HwcDisplay() {} |
| |
| bool HwcDisplay::SetClientTarget(const native_handle_t* handle, |
| base::unique_fd fence) { |
| if (handle) |
| buffer_ = CreateGraphicBuffer(handle, buffer_metadata_); |
| |
| fence_ = new Fence(fence.release()); |
| return true; |
| } |
| |
| void HwcDisplay::SetClientTargetMetadata( |
| const IVrComposerClient::BufferMetadata& metadata) { |
| buffer_metadata_ = metadata; |
| } |
| |
| HwcLayer* HwcDisplay::CreateLayer() { |
| uint64_t layer_id = layer_ids_++; |
| layers_.push_back(HwcLayer(layer_id)); |
| return &layers_.back(); |
| } |
| |
| HwcLayer* HwcDisplay::GetLayer(Layer id) { |
| for (size_t i = 0; i < layers_.size(); ++i) |
| if (layers_[i].info.id == id) |
| return &layers_[i]; |
| |
| return nullptr; |
| } |
| |
| bool HwcDisplay::DestroyLayer(Layer id) { |
| for (auto it = layers_.begin(); it != layers_.end(); ++it) { |
| if (it->info.id == id) { |
| layers_.erase(it); |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| void HwcDisplay::GetChangedCompositionTypes( |
| std::vector<Layer>* layer_ids, |
| std::vector<IComposerClient::Composition>* types) { |
| std::sort(layers_.begin(), layers_.end(), |
| [](const auto& lhs, const auto& rhs) { |
| return lhs.info.z_order < rhs.info.z_order; |
| }); |
| |
| const size_t no_layer = std::numeric_limits<size_t>::max(); |
| size_t first_client_layer = no_layer, last_client_layer = no_layer; |
| for (size_t i = 0; i < layers_.size(); ++i) { |
| switch (layers_[i].composition_type) { |
| case IComposerClient::Composition::SOLID_COLOR: |
| case IComposerClient::Composition::CURSOR: |
| case IComposerClient::Composition::SIDEBAND: |
| if (first_client_layer == no_layer) |
| first_client_layer = i; |
| |
| last_client_layer = i; |
| break; |
| default: |
| break; |
| } |
| } |
| |
| for (size_t i = 0; i < layers_.size(); ++i) { |
| if (i >= first_client_layer && i <= last_client_layer) { |
| if (layers_[i].composition_type != IComposerClient::Composition::CLIENT) { |
| layer_ids->push_back(layers_[i].info.id); |
| types->push_back(IComposerClient::Composition::CLIENT); |
| layers_[i].composition_type = IComposerClient::Composition::CLIENT; |
| } |
| |
| continue; |
| } |
| |
| if (layers_[i].composition_type != IComposerClient::Composition::DEVICE) { |
| layer_ids->push_back(layers_[i].info.id); |
| types->push_back(IComposerClient::Composition::DEVICE); |
| layers_[i].composition_type = IComposerClient::Composition::DEVICE; |
| } |
| } |
| } |
| |
| Error HwcDisplay::GetFrame( |
| std::vector<ComposerView::ComposerLayer>* out_frames) { |
| bool queued_client_target = false; |
| std::vector<ComposerView::ComposerLayer> frame; |
| for (const auto& layer : layers_) { |
| if (layer.composition_type == IComposerClient::Composition::CLIENT) { |
| if (queued_client_target) |
| continue; |
| |
| if (!buffer_.get()) { |
| ALOGE("Client composition requested but no client target buffer"); |
| return Error::BAD_LAYER; |
| } |
| |
| ComposerView::ComposerLayer client_target_layer = { |
| .buffer = buffer_, |
| .fence = fence_.get() ? fence_ : new Fence(-1), |
| .display_frame = {0, 0, static_cast<int32_t>(buffer_->getWidth()), |
| static_cast<int32_t>(buffer_->getHeight())}, |
| .crop = {0.0f, 0.0f, static_cast<float>(buffer_->getWidth()), |
| static_cast<float>(buffer_->getHeight())}, |
| .blend_mode = IComposerClient::BlendMode::NONE, |
| }; |
| |
| frame.push_back(client_target_layer); |
| queued_client_target = true; |
| } else { |
| if (!layer.info.buffer.get() || !layer.info.fence.get()) { |
| ALOGV("Layer requested without valid buffer"); |
| continue; |
| } |
| |
| frame.push_back(layer.info); |
| } |
| } |
| |
| out_frames->swap(frame); |
| return Error::NONE; |
| } |
| |
| std::vector<Layer> HwcDisplay::UpdateLastFrameAndGetLastFrameLayers() { |
| std::vector<Layer> last_frame_layers; |
| last_frame_layers.swap(last_frame_layers_ids_); |
| |
| for (const auto& layer : layers_) |
| last_frame_layers_ids_.push_back(layer.info.id); |
| |
| return last_frame_layers; |
| } |
| |
| void HwcDisplay::SetColorTransform(const float* matrix, int32_t hint) { |
| color_transform_hint_ = hint; |
| if (matrix) |
| memcpy(color_transform_, matrix, sizeof(color_transform_)); |
| } |
| |
| void HwcDisplay::dumpDebugInfo(std::string* result) const { |
| if (!result) { |
| return; |
| } |
| *result += StringPrintf("HwcDisplay: width: %d, height: %d, layers size: %zu, colormode: %d\ |
| , config: %d\n", width_, height_, layers_.size(), color_mode_, active_config_); |
| *result += StringPrintf("HwcDisplay buffer metadata: width: %d, height: %d, stride: %d,\ |
| layerCount: %d, pixelFormat: %d\n", buffer_metadata_.width, buffer_metadata_.height, |
| buffer_metadata_.stride, buffer_metadata_.layerCount, buffer_metadata_.format); |
| for (const auto& layer : layers_) { |
| layer.dumpDebugInfo(result); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // VrHwcClient |
| |
| VrHwc::VrHwc() {} |
| |
| VrHwc::~VrHwc() {} |
| |
| bool VrHwc::hasCapability(hwc2_capability_t /* capability */) { return false; } |
| |
| void VrHwc::registerEventCallback(EventCallback* callback) { |
| { |
| std::lock_guard<std::mutex> guard(mutex_); |
| event_callback_ = callback; |
| int32_t width, height; |
| GetPrimaryDisplaySize(&width, &height); |
| // Create the primary display late to avoid initialization issues between |
| // VR HWC and SurfaceFlinger. |
| displays_[kDefaultDisplayId].reset(new HwcDisplay(width, height)); |
| } |
| event_callback_->onHotplug(kDefaultDisplayId, |
| IComposerCallback::Connection::CONNECTED); |
| } |
| |
| void VrHwc::unregisterEventCallback() { |
| std::lock_guard<std::mutex> guard(mutex_); |
| event_callback_ = nullptr; |
| } |
| |
| uint32_t VrHwc::getMaxVirtualDisplayCount() { return 1; } |
| |
| Error VrHwc::createVirtualDisplay(uint32_t width, uint32_t height, |
| PixelFormat* format, Display* outDisplay) { |
| *format = PixelFormat::RGBA_8888; |
| *outDisplay = display_count_; |
| displays_[display_count_].reset(new HwcDisplay(width, height)); |
| display_count_++; |
| return Error::NONE; |
| } |
| |
| Error VrHwc::destroyVirtualDisplay(Display display) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| if (display == kDefaultDisplayId || displays_.erase(display) == 0) |
| return Error::BAD_DISPLAY; |
| ComposerView::Frame frame; |
| frame.display_id = display; |
| frame.removed = true; |
| if (observer_) |
| observer_->OnNewFrame(frame); |
| return Error::NONE; |
| } |
| |
| Error VrHwc::createLayer(Display display, Layer* outLayer) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| HwcLayer* layer = display_ptr->CreateLayer(); |
| *outLayer = layer->info.id; |
| return Error::NONE; |
| } |
| |
| Error VrHwc::destroyLayer(Display display, Layer layer) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) { |
| return Error::BAD_DISPLAY; |
| } |
| |
| return display_ptr->DestroyLayer(layer) ? Error::NONE : Error::BAD_LAYER; |
| } |
| |
| Error VrHwc::getActiveConfig(Display display, Config* outConfig) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| if (!FindDisplay(display)) |
| return Error::BAD_DISPLAY; |
| *outConfig = kDefaultConfigId; |
| return Error::NONE; |
| } |
| |
| Error VrHwc::getClientTargetSupport(Display /* display */, uint32_t /* width */, |
| uint32_t /* height */, |
| PixelFormat /* format */, |
| Dataspace /* dataspace */) { |
| return Error::NONE; |
| } |
| |
| Error VrHwc::getColorModes(Display /* display */, |
| hidl_vec<ColorMode>* outModes) { |
| std::vector<ColorMode> color_modes(1, ColorMode::NATIVE); |
| *outModes = hidl_vec<ColorMode>(color_modes); |
| return Error::NONE; |
| } |
| |
| Error VrHwc::getDisplayAttribute(Display display, Config config, |
| IComposerClient::Attribute attribute, |
| int32_t* outValue) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) { |
| return Error::BAD_DISPLAY; |
| } |
| if (config != kDefaultConfigId) { |
| return Error::BAD_CONFIG; |
| } |
| |
| switch (attribute) { |
| case IComposerClient::Attribute::WIDTH: |
| *outValue = display_ptr->width(); |
| break; |
| case IComposerClient::Attribute::HEIGHT: |
| *outValue = display_ptr->height(); |
| break; |
| case IComposerClient::Attribute::VSYNC_PERIOD: |
| { |
| int error = 0; |
| auto display_client = display::DisplayClient::Create(&error); |
| if (!display_client) { |
| ALOGE("Could not connect to display service : %s(%d)", |
| strerror(error), error); |
| // Return a default value of 30 fps |
| *outValue = 1000 * 1000 * 1000 / 30; |
| } else { |
| auto metrics = display_client->GetDisplayMetrics(); |
| *outValue = metrics.get().vsync_period_ns; |
| } |
| } |
| break; |
| case IComposerClient::Attribute::DPI_X: |
| case IComposerClient::Attribute::DPI_Y: |
| { |
| constexpr int32_t kDefaultDPI = 300; |
| int32_t dpi = property_get_int32("ro.vr.hwc.dpi", kDefaultDPI); |
| if (dpi <= 0) { |
| dpi = kDefaultDPI; |
| } |
| *outValue = 1000 * dpi; |
| } |
| break; |
| default: |
| return Error::BAD_PARAMETER; |
| } |
| |
| return Error::NONE; |
| } |
| |
| Error VrHwc::getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| if (!FindDisplay(display)) |
| return Error::BAD_DISPLAY; |
| std::vector<Config> configs(1, kDefaultConfigId); |
| *outConfigs = hidl_vec<Config>(configs); |
| return Error::NONE; |
| } |
| |
| Error VrHwc::getDisplayName(Display /* display */, hidl_string* outName) { |
| *outName = hidl_string(); |
| return Error::NONE; |
| } |
| |
| Error VrHwc::getDisplayType(Display display, |
| IComposerClient::DisplayType* outType) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) { |
| *outType = IComposerClient::DisplayType::INVALID; |
| return Error::BAD_DISPLAY; |
| } |
| |
| if (display == kDefaultDisplayId) |
| *outType = IComposerClient::DisplayType::PHYSICAL; |
| else |
| *outType = IComposerClient::DisplayType::VIRTUAL; |
| |
| return Error::NONE; |
| } |
| |
| Error VrHwc::getDozeSupport(Display display, bool* outSupport) { |
| *outSupport = false; |
| std::lock_guard<std::mutex> guard(mutex_); |
| if (!FindDisplay(display)) |
| return Error::BAD_DISPLAY; |
| return Error::NONE; |
| } |
| |
| Error VrHwc::getHdrCapabilities(Display /* display */, |
| hidl_vec<Hdr>* /* outTypes */, |
| float* outMaxLuminance, |
| float* outMaxAverageLuminance, |
| float* outMinLuminance) { |
| *outMaxLuminance = 0; |
| *outMaxAverageLuminance = 0; |
| *outMinLuminance = 0; |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setActiveConfig(Display display, Config config) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| if (config != kDefaultConfigId) |
| return Error::BAD_CONFIG; |
| |
| display_ptr->set_active_config(config); |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setColorMode(Display display, ColorMode mode) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| display_ptr->set_color_mode(mode); |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setPowerMode(Display display, IComposerClient::PowerMode mode) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| display_ptr->set_power_mode(mode); |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setVsyncEnabled(Display display, IComposerClient::Vsync enabled) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| display_ptr->set_vsync_enabled(enabled); |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setColorTransform(Display display, const float* matrix, |
| int32_t hint) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| display_ptr->SetColorTransform(matrix, hint); |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setClientTarget(Display display, buffer_handle_t target, |
| int32_t acquireFence, int32_t /* dataspace */, |
| const std::vector<hwc_rect_t>& /* damage */) { |
| base::unique_fd fence(acquireFence); |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| if (target == nullptr) |
| return Error::NONE; |
| |
| if (!display_ptr->SetClientTarget(target, std::move(fence))) |
| return Error::BAD_PARAMETER; |
| |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setOutputBuffer(Display display, buffer_handle_t /* buffer */, |
| int32_t releaseFence) { |
| base::unique_fd fence(releaseFence); |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| // TODO(dnicoara): Is it necessary to do anything here? |
| return Error::NONE; |
| } |
| |
| Error VrHwc::validateDisplay( |
| Display display, std::vector<Layer>* outChangedLayers, |
| std::vector<IComposerClient::Composition>* outCompositionTypes, |
| uint32_t* /* outDisplayRequestMask */, |
| std::vector<Layer>* /* outRequestedLayers */, |
| std::vector<uint32_t>* /* outRequestMasks */) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| display_ptr->GetChangedCompositionTypes(outChangedLayers, |
| outCompositionTypes); |
| return Error::NONE; |
| } |
| |
| Error VrHwc::acceptDisplayChanges(Display /* display */) { return Error::NONE; } |
| |
| Error VrHwc::presentDisplay(Display display, int32_t* outPresentFence, |
| std::vector<Layer>* outLayers, |
| std::vector<int32_t>* outReleaseFences) { |
| *outPresentFence = -1; |
| outLayers->clear(); |
| outReleaseFences->clear(); |
| |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| ComposerView::Frame frame; |
| std::vector<Layer> last_frame_layers; |
| Error status = display_ptr->GetFrame(&frame.layers); |
| frame.display_id = display; |
| frame.display_width = display_ptr->width(); |
| frame.display_height = display_ptr->height(); |
| frame.active_config = display_ptr->active_config(); |
| frame.power_mode = display_ptr->power_mode(); |
| frame.vsync_enabled = display_ptr->vsync_enabled(); |
| frame.color_transform_hint = display_ptr->color_transform_hint(); |
| frame.color_mode = display_ptr->color_mode(); |
| memcpy(frame.color_transform, display_ptr->color_transform(), |
| sizeof(frame.color_transform)); |
| if (status != Error::NONE) |
| return status; |
| |
| last_frame_layers = display_ptr->UpdateLastFrameAndGetLastFrameLayers(); |
| |
| base::unique_fd fence; |
| if (observer_) |
| fence = observer_->OnNewFrame(frame); |
| |
| if (fence.get() < 0) |
| return Error::NONE; |
| |
| *outPresentFence = dup(fence.get()); |
| outLayers->swap(last_frame_layers); |
| for (size_t i = 0; i < outLayers->size(); ++i) |
| outReleaseFences->push_back(dup(fence.get())); |
| |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setLayerCursorPosition(Display display, Layer layer, int32_t x, |
| int32_t y) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| HwcLayer* hwc_layer = display_ptr->GetLayer(layer); |
| if (!hwc_layer) |
| return Error::BAD_LAYER; |
| |
| hwc_layer->info.cursor_x = x; |
| hwc_layer->info.cursor_y = y; |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setLayerBuffer(Display display, Layer layer, |
| buffer_handle_t buffer, int32_t acquireFence) { |
| base::unique_fd fence(acquireFence); |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| HwcLayer* hwc_layer = display_ptr->GetLayer(layer); |
| if (!hwc_layer) |
| return Error::BAD_LAYER; |
| |
| hwc_layer->info.buffer = CreateGraphicBuffer( |
| buffer, hwc_layer->buffer_metadata); |
| hwc_layer->info.fence = new Fence(fence.release()); |
| |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setLayerSurfaceDamage(Display display, Layer layer, |
| const std::vector<hwc_rect_t>& damage) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| HwcLayer* hwc_layer = display_ptr->GetLayer(layer); |
| if (!hwc_layer) |
| return Error::BAD_LAYER; |
| |
| hwc_layer->info.damaged_regions = damage; |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setLayerBlendMode(Display display, Layer layer, int32_t mode) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| HwcLayer* hwc_layer = display_ptr->GetLayer(layer); |
| if (!hwc_layer) |
| return Error::BAD_LAYER; |
| |
| hwc_layer->info.blend_mode = |
| static_cast<ComposerView::ComposerLayer::BlendMode>(mode); |
| |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setLayerColor(Display display, Layer layer, |
| IComposerClient::Color color) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| HwcLayer* hwc_layer = display_ptr->GetLayer(layer); |
| if (!hwc_layer) |
| return Error::BAD_LAYER; |
| |
| hwc_layer->info.color = color; |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setLayerCompositionType(Display display, Layer layer, |
| int32_t type) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| HwcLayer* hwc_layer = display_ptr->GetLayer(layer); |
| if (!hwc_layer) |
| return Error::BAD_LAYER; |
| |
| hwc_layer->composition_type = static_cast<HwcLayer::Composition>(type); |
| |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setLayerDataspace(Display display, Layer layer, |
| int32_t dataspace) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| HwcLayer* hwc_layer = display_ptr->GetLayer(layer); |
| if (!hwc_layer) |
| return Error::BAD_LAYER; |
| |
| hwc_layer->info.dataspace = dataspace; |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setLayerDisplayFrame(Display display, Layer layer, |
| const hwc_rect_t& frame) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| HwcLayer* hwc_layer = display_ptr->GetLayer(layer); |
| if (!hwc_layer) |
| return Error::BAD_LAYER; |
| |
| hwc_layer->info.display_frame = |
| {frame.left, frame.top, frame.right, frame.bottom}; |
| |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setLayerPlaneAlpha(Display display, Layer layer, float alpha) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| HwcLayer* hwc_layer = display_ptr->GetLayer(layer); |
| if (!hwc_layer) |
| return Error::BAD_LAYER; |
| |
| hwc_layer->info.alpha = alpha; |
| |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setLayerSidebandStream(Display display, Layer /* layer */, |
| buffer_handle_t /* stream */) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| if (!FindDisplay(display)) |
| return Error::BAD_DISPLAY; |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setLayerSourceCrop(Display display, Layer layer, |
| const hwc_frect_t& crop) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| HwcLayer* hwc_layer = display_ptr->GetLayer(layer); |
| if (!hwc_layer) |
| return Error::BAD_LAYER; |
| |
| hwc_layer->info.crop = {crop.left, crop.top, crop.right, crop.bottom}; |
| |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setLayerTransform(Display display, Layer layer, |
| int32_t transform) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| HwcLayer* hwc_layer = display_ptr->GetLayer(layer); |
| if (!hwc_layer) |
| return Error::BAD_LAYER; |
| |
| hwc_layer->info.transform = transform; |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setLayerVisibleRegion(Display display, Layer layer, |
| const std::vector<hwc_rect_t>& visible) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| HwcLayer* hwc_layer = display_ptr->GetLayer(layer); |
| if (!hwc_layer) |
| return Error::BAD_LAYER; |
| |
| hwc_layer->info.visible_regions = visible; |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setLayerZOrder(Display display, Layer layer, uint32_t z) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| HwcLayer* hwc_layer = display_ptr->GetLayer(layer); |
| if (!hwc_layer) |
| return Error::BAD_LAYER; |
| |
| hwc_layer->info.z_order = z; |
| |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setLayerInfo(Display display, Layer layer, uint32_t type, |
| uint32_t appId) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| HwcLayer* hwc_layer = display_ptr->GetLayer(layer); |
| if (!hwc_layer) |
| return Error::BAD_LAYER; |
| |
| hwc_layer->info.type = type; |
| hwc_layer->info.app_id = appId; |
| |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setClientTargetMetadata( |
| Display display, const IVrComposerClient::BufferMetadata& metadata) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| display_ptr->SetClientTargetMetadata(metadata); |
| |
| return Error::NONE; |
| } |
| |
| Error VrHwc::setLayerBufferMetadata( |
| Display display, Layer layer, |
| const IVrComposerClient::BufferMetadata& metadata) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| auto display_ptr = FindDisplay(display); |
| if (!display_ptr) |
| return Error::BAD_DISPLAY; |
| |
| HwcLayer* hwc_layer = display_ptr->GetLayer(layer); |
| if (!hwc_layer) |
| return Error::BAD_LAYER; |
| |
| hwc_layer->buffer_metadata = metadata; |
| |
| return Error::NONE; |
| } |
| |
| Return<void> VrHwc::getCapabilities(getCapabilities_cb hidl_cb) { |
| hidl_cb(hidl_vec<Capability>()); |
| return Void(); |
| } |
| |
| Return<void> VrHwc::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) { |
| std::string result; |
| |
| { |
| std::lock_guard<std::mutex> guard(mutex_); |
| result = "\nVrHwc states:\n"; |
| for (const auto& pair : displays_) { |
| result += StringPrintf("Display id: %lu\n", (unsigned long)pair.first); |
| pair.second->dumpDebugInfo(&result); |
| } |
| result += "\n"; |
| } |
| |
| hidl_cb(hidl_string(result)); |
| return Void(); |
| } |
| |
| Return<void> VrHwc::createClient(createClient_cb hidl_cb) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| |
| Error status = Error::NONE; |
| sp<VrComposerClient> client; |
| if (!client_.promote().get()) { |
| client = new VrComposerClient(*this); |
| } else { |
| ALOGE("Already have a client"); |
| status = Error::NO_RESOURCES; |
| } |
| |
| client_ = client; |
| hidl_cb(status, client); |
| return Void(); |
| } |
| |
| void VrHwc::ForceDisplaysRefresh() { |
| std::lock_guard<std::mutex> guard(mutex_); |
| if (event_callback_ != nullptr) { |
| for (const auto& pair : displays_) |
| event_callback_->onRefresh(pair.first); |
| } |
| } |
| |
| void VrHwc::RegisterObserver(Observer* observer) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| if (observer_) |
| ALOGE("Overwriting observer"); |
| else |
| observer_ = observer; |
| } |
| |
| void VrHwc::UnregisterObserver(Observer* observer) { |
| std::lock_guard<std::mutex> guard(mutex_); |
| if (observer != observer_) |
| ALOGE("Trying to unregister unknown observer"); |
| else |
| observer_ = nullptr; |
| } |
| |
| HwcDisplay* VrHwc::FindDisplay(Display display) { |
| auto iter = displays_.find(display); |
| return iter == displays_.end() ? nullptr : iter->second.get(); |
| } |
| |
| void HwcLayer::dumpDebugInfo(std::string* result) const { |
| if (!result) { |
| return; |
| } |
| *result += StringPrintf("Layer: composition_type: %d, type: %d, app_id: %d, z_order: %d,\ |
| cursor_x: %d, cursor_y: %d, color(rgba): (%d,%d,%d,%d), dataspace: %d, transform: %d,\ |
| display_frame(LTRB): (%d,%d,%d,%d), crop(LTRB): (%.1f,%.1f,%.1f,%.1f), blend_mode: %d\n", |
| composition_type, info.type, info.app_id, info.z_order, info.cursor_x, info.cursor_y, |
| info.color.r, info.color.g, info.color.b, info.color.a, info.dataspace, info.transform, |
| info.display_frame.left, info.display_frame.top, info.display_frame.right, |
| info.display_frame.bottom, info.crop.left, info.crop.top, info.crop.right, |
| info.crop.bottom, info.blend_mode); |
| *result += StringPrintf("Layer buffer metadata: width: %d, height: %d, stride: %d, layerCount: %d\ |
| , pixelFormat: %d\n", buffer_metadata.width, buffer_metadata.height, buffer_metadata.stride, |
| buffer_metadata.layerCount, buffer_metadata.format); |
| } |
| |
| } // namespace dvr |
| } // namespace android |