/* * 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 <binder/IServiceManager.h> #include <cutils/properties.h> #include <private/dvr/display_client.h> #include <ui/Fence.h> #include <utils/Trace.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() { vsync_callback_ = new VsyncCallback; } VrHwc::~VrHwc() { vsync_callback_->SetEventCallback(nullptr); } bool VrHwc::hasCapability(hwc2_capability_t /* capability */) { return false; } void VrHwc::registerEventCallback(EventCallback* callback) { std::unique_lock<std::mutex> lock(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)); // Surface flinger will make calls back into vr_hwc when it receives the // onHotplug() call, so it's important to release mutex_ here. lock.unlock(); event_callback_->onHotplug(kDefaultDisplayId, IComposerCallback::Connection::CONNECTED); lock.lock(); UpdateVsyncCallbackEnabledLocked(); } void VrHwc::unregisterEventCallback() { std::lock_guard<std::mutex> guard(mutex_); event_callback_ = nullptr; UpdateVsyncCallbackEnabledLocked(); } 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 */) { std::lock_guard<std::mutex> guard(mutex_); if (!FindDisplay(display)) return Error::BAD_DISPLAY; 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; if (mode < ColorMode::NATIVE || mode > ColorMode::DISPLAY_P3) return Error::BAD_PARAMETER; display_ptr->set_color_mode(mode); return Error::NONE; } Error VrHwc::setPowerMode(Display display, IComposerClient::PowerMode mode) { bool dozeSupported = false; Error dozeSupportError = getDozeSupport(display, &dozeSupported); if (dozeSupportError != Error::NONE) return dozeSupportError; std::lock_guard<std::mutex> guard(mutex_); auto display_ptr = FindDisplay(display); if (!display_ptr) return Error::BAD_DISPLAY; if (mode < IComposerClient::PowerMode::OFF || mode > IComposerClient::PowerMode::DOZE_SUSPEND) { return Error::BAD_PARAMETER; } if (!dozeSupported && (mode == IComposerClient::PowerMode::DOZE || mode == IComposerClient::PowerMode::DOZE_SUSPEND)) { return Error::UNSUPPORTED; } 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; if (enabled != IComposerClient::Vsync::ENABLE && enabled != IComposerClient::Vsync::DISABLE) { return Error::BAD_PARAMETER; } Error set_vsync_result = Error::NONE; if (display == kDefaultDisplayId) { sp<IVsyncService> vsync_service = interface_cast<IVsyncService>( defaultServiceManager()->getService( String16(IVsyncService::GetServiceName()))); if (vsync_service == nullptr) { ALOGE("Failed to get vsync service"); return Error::NO_RESOURCES; } if (enabled == IComposerClient::Vsync::ENABLE) { ALOGI("Enable vsync"); display_ptr->set_vsync_enabled(true); status_t result = vsync_service->registerCallback(vsync_callback_); if (result != OK) { ALOGE("%s service registerCallback() failed: %s (%d)", IVsyncService::GetServiceName(), strerror(-result), result); set_vsync_result = Error::NO_RESOURCES; } } else if (enabled == IComposerClient::Vsync::DISABLE) { ALOGI("Disable vsync"); display_ptr->set_vsync_enabled(false); status_t result = vsync_service->unregisterCallback(vsync_callback_); if (result != OK) { ALOGE("%s service unregisterCallback() failed: %s (%d)", IVsyncService::GetServiceName(), strerror(-result), result); set_vsync_result = Error::NO_RESOURCES; } } UpdateVsyncCallbackEnabledLocked(); } return set_vsync_result; } 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() ? IComposerClient::Vsync::ENABLE : IComposerClient::Vsync::DISABLE; 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 VrHwc::UpdateVsyncCallbackEnabledLocked() { auto primary_display = FindDisplay(kDefaultDisplayId); LOG_ALWAYS_FATAL_IF(event_callback_ != nullptr && primary_display == nullptr, "Should have created the primary display by now"); bool send_vsync = event_callback_ != nullptr && primary_display->vsync_enabled(); vsync_callback_->SetEventCallback(send_vsync ? event_callback_ : nullptr); } 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); } status_t VrHwc::VsyncCallback::onVsync(int64_t vsync_timestamp) { ATRACE_NAME("vr_hwc onVsync"); std::lock_guard<std::mutex> guard(mutex_); if (callback_ != nullptr) callback_->onVsync(kDefaultDisplayId, vsync_timestamp); return OK; } void VrHwc::VsyncCallback::SetEventCallback(EventCallback* callback) { std::lock_guard<std::mutex> guard(mutex_); callback_ = callback; } } // namespace dvr } // namespace android