| /* |
| * 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 "base_composer.h" |
| |
| #include <string.h> |
| |
| #include <log/log.h> |
| #include <hardware/gralloc.h> |
| |
| #include "common/vsoc/lib/screen_region_view.h" |
| #include "guest/hals/gralloc/legacy/gralloc_vsoc_priv.h" |
| |
| using vsoc::screen::ScreenRegionView; |
| |
| namespace cvd { |
| |
| namespace { |
| |
| void BroadcastFrameBufferChanged(int index) { |
| ScreenRegionView::GetInstance()->BroadcastNewFrame( |
| static_cast<uint32_t>(index)); |
| } |
| |
| } // namespace |
| |
| BaseComposer::BaseComposer(int64_t vsync_base_timestamp, |
| int32_t vsync_period_ns) |
| : vsync_base_timestamp_(vsync_base_timestamp), |
| vsync_period_ns_(vsync_period_ns), |
| fb_broadcaster_(BroadcastFrameBufferChanged) { |
| hw_get_module(GRALLOC_HARDWARE_MODULE_ID, |
| reinterpret_cast<const hw_module_t**>(&gralloc_module_)); |
| } |
| |
| BaseComposer::~BaseComposer() {} |
| |
| FbBroadcaster BaseComposer::ReplaceFbBroadcaster(FbBroadcaster fb_broadcaster) { |
| FbBroadcaster tmp = fb_broadcaster_; |
| fb_broadcaster_ = fb_broadcaster; |
| return tmp; |
| } |
| |
| void BaseComposer::Dump(char* buff __unused, int buff_len __unused) {} |
| |
| void BaseComposer::Broadcast(int fb_index) { |
| fb_broadcaster_(fb_index); |
| } |
| |
| int BaseComposer::PostFrameBufferTarget(buffer_handle_t buffer_handle) { |
| int fb_index = NextScreenBuffer(); |
| if (fb_index < 0) { |
| ALOGE("Could not get the next buffer. Is the screen region large enough?"); |
| return -1; |
| } |
| auto screen_view = ScreenRegionView::GetInstance(); |
| void* frame_buffer = screen_view->GetBuffer(fb_index); |
| const private_handle_t* p_handle = |
| reinterpret_cast<const private_handle_t*>(buffer_handle); |
| void* buffer; |
| int retval = gralloc_module_->lock(gralloc_module_, buffer_handle, |
| GRALLOC_USAGE_SW_READ_OFTEN, 0, 0, |
| p_handle->x_res, p_handle->y_res, &buffer); |
| if (retval != 0) { |
| ALOGE("Got error code %d from lock function", retval); |
| return -1; |
| } |
| memcpy(frame_buffer, buffer, screen_view->buffer_size()); |
| Broadcast(fb_index); |
| return 0; |
| } // namespace cvd |
| |
| int BaseComposer::PrepareLayers(size_t num_layers, vsoc_hwc_layer* layers) { |
| // find unsupported overlays |
| for (size_t i = 0; i < num_layers; i++) { |
| if (IS_TARGET_FRAMEBUFFER(layers[i].compositionType)) { |
| continue; |
| } |
| layers[i].compositionType = HWC_FRAMEBUFFER; |
| } |
| return 0; |
| } |
| |
| int BaseComposer::SetLayers(size_t num_layers, vsoc_hwc_layer* layers) { |
| for (size_t idx = 0; idx < num_layers; idx++) { |
| if (IS_TARGET_FRAMEBUFFER(layers[idx].compositionType)) { |
| return PostFrameBufferTarget(layers[idx].handle); |
| } |
| } |
| return -1; |
| } |
| |
| int BaseComposer::NextScreenBuffer() { |
| int num_buffers = ScreenRegionView::GetInstance()->number_of_buffers(); |
| last_frame_buffer_ = |
| num_buffers > 0 ? (last_frame_buffer_ + 1) % num_buffers : -1; |
| return last_frame_buffer_; |
| } |
| |
| } // namespace cvd |