display_surface.cpp revision f0a7bd033941e26e380232a0515e903cf8e678e5
1#include "display_surface.h" 2 3#include <utils/Trace.h> 4 5#include <private/dvr/platform_defines.h> 6 7#include "display_service.h" 8#include "hardware_composer.h" 9 10#define LOCAL_TRACE 1 11 12using android::pdx::BorrowedChannelHandle; 13using android::pdx::LocalChannelHandle; 14using android::pdx::Message; 15using android::pdx::RemoteChannelHandle; 16using android::pdx::Status; 17using android::pdx::rpc::DispatchRemoteMethod; 18using android::pdx::rpc::IfAnyOf; 19 20namespace android { 21namespace dvr { 22 23DisplaySurface::DisplaySurface(DisplayService* service, int surface_id, 24 int process_id, int width, int height, 25 int format, int usage, int flags) 26 : SurfaceChannel(service, surface_id, SurfaceTypeEnum::Normal, 27 sizeof(DisplaySurfaceMetadata)), 28 process_id_(process_id), 29 acquired_buffers_(kMaxPostedBuffers), 30 video_mesh_surfaces_updated_(false), 31 width_(width), 32 height_(height), 33 format_(format), 34 usage_(usage), 35 flags_(flags), 36 client_visible_(false), 37 client_z_order_(0), 38 client_exclude_from_blur_(false), 39 client_blur_behind_(false), 40 manager_visible_(false), 41 manager_z_order_(0), 42 manager_blur_(0.0f), 43 layer_order_(0), 44 allocated_buffer_index_(0) {} 45 46DisplaySurface::~DisplaySurface() { 47 ALOGD_IF(LOCAL_TRACE, 48 "DisplaySurface::~DisplaySurface: surface_id=%d process_id=%d", 49 surface_id(), process_id_); 50} 51 52void DisplaySurface::ManagerSetVisible(bool visible) { 53 std::lock_guard<std::mutex> autolock(lock_); 54 manager_visible_ = visible; 55} 56 57void DisplaySurface::ManagerSetZOrder(int z_order) { 58 std::lock_guard<std::mutex> autolock(lock_); 59 manager_z_order_ = z_order; 60} 61 62void DisplaySurface::ManagerSetBlur(float blur) { 63 std::lock_guard<std::mutex> autolock(lock_); 64 manager_blur_ = blur; 65} 66 67void DisplaySurface::ClientSetVisible(bool visible) { 68 std::lock_guard<std::mutex> autolock(lock_); 69 client_visible_ = visible; 70} 71 72void DisplaySurface::ClientSetZOrder(int z_order) { 73 std::lock_guard<std::mutex> autolock(lock_); 74 client_z_order_ = z_order; 75} 76 77void DisplaySurface::ClientSetExcludeFromBlur(bool exclude_from_blur) { 78 std::lock_guard<std::mutex> autolock(lock_); 79 client_exclude_from_blur_ = exclude_from_blur; 80} 81 82void DisplaySurface::ClientSetBlurBehind(bool blur_behind) { 83 std::lock_guard<std::mutex> autolock(lock_); 84 client_blur_behind_ = blur_behind; 85} 86 87void DisplaySurface::DequeueBuffersLocked() { 88 if (consumer_queue_ == nullptr) { 89 ALOGE( 90 "DisplaySurface::DequeueBuffersLocked: Consumer queue is not " 91 "initialized."); 92 return; 93 } 94 95 size_t slot; 96 uint64_t sequence; 97 while (true) { 98 LocalHandle acquire_fence; 99 auto buffer_consumer = 100 consumer_queue_->Dequeue(0, &slot, &sequence, &acquire_fence); 101 if (!buffer_consumer) { 102 ALOGD_IF(TRACE, 103 "DisplaySurface::DequeueBuffersLocked: We have dequeued all " 104 "available buffers."); 105 return; 106 } 107 108 // Save buffer index, associated with the buffer id so that it can be looked 109 // up later. 110 int buffer_id = buffer_consumer->id(); 111 if (buffer_id_to_index_.find(buffer_id) == buffer_id_to_index_.end()) { 112 buffer_id_to_index_[buffer_id] = allocated_buffer_index_; 113 ++allocated_buffer_index_; 114 } 115 116 if (!IsVisible()) { 117 ATRACE_NAME("DropFrameOnInvisibleSurface"); 118 ALOGD_IF(TRACE, 119 "DisplaySurface::DequeueBuffersLocked: Discarding buffer_id=%d " 120 "on invisible surface.", 121 buffer_consumer->id()); 122 buffer_consumer->Discard(); 123 continue; 124 } 125 126 if (acquired_buffers_.IsFull()) { 127 ALOGE( 128 "DisplaySurface::DequeueBuffersLocked: Posted buffers full, " 129 "overwriting."); 130 acquired_buffers_.PopBack(); 131 } 132 133 acquired_buffers_.Append( 134 AcquiredBuffer(buffer_consumer, std::move(acquire_fence), sequence)); 135 } 136} 137 138AcquiredBuffer DisplaySurface::AcquireCurrentBuffer() { 139 std::lock_guard<std::mutex> autolock(lock_); 140 DequeueBuffersLocked(); 141 142 if (acquired_buffers_.IsEmpty()) { 143 ALOGE( 144 "DisplaySurface::AcquireCurrentBuffer: attempt to acquire buffer when " 145 "none are posted."); 146 return AcquiredBuffer(); 147 } 148 AcquiredBuffer buffer = std::move(acquired_buffers_.Front()); 149 acquired_buffers_.PopFront(); 150 ALOGD_IF(TRACE, "DisplaySurface::AcquireCurrentBuffer: buffer: %p", 151 buffer.buffer().get()); 152 return buffer; 153} 154 155AcquiredBuffer DisplaySurface::AcquireNewestAvailableBuffer( 156 AcquiredBuffer* skipped_buffer) { 157 std::lock_guard<std::mutex> autolock(lock_); 158 DequeueBuffersLocked(); 159 160 AcquiredBuffer buffer; 161 int frames = 0; 162 // Basic latency stopgap for when the application misses a frame: 163 // If the application recovers on the 2nd or 3rd (etc) frame after 164 // missing, this code will skip frames to catch up by checking if 165 // the next frame is also available. 166 while (!acquired_buffers_.IsEmpty() && 167 acquired_buffers_.Front().IsAvailable()) { 168 // Capture the skipped buffer into the result parameter. 169 // Note that this API only supports skipping one buffer per vsync. 170 if (frames > 0 && skipped_buffer) 171 *skipped_buffer = std::move(buffer); 172 ++frames; 173 buffer = std::move(acquired_buffers_.Front()); 174 acquired_buffers_.PopFront(); 175 if (frames == 2) 176 break; 177 } 178 ALOGD_IF(TRACE, "DisplaySurface::AcquireNewestAvailableBuffer: buffer: %p", 179 buffer.buffer().get()); 180 return buffer; 181} 182 183uint32_t DisplaySurface::GetRenderBufferIndex(int buffer_id) { 184 std::lock_guard<std::mutex> autolock(lock_); 185 186 if (buffer_id_to_index_.find(buffer_id) == buffer_id_to_index_.end()) { 187 ALOGW("DisplaySurface::GetRenderBufferIndex: unknown buffer_id %d.", 188 buffer_id); 189 return 0; 190 } 191 return buffer_id_to_index_[buffer_id]; 192} 193 194bool DisplaySurface::IsBufferAvailable() { 195 std::lock_guard<std::mutex> autolock(lock_); 196 DequeueBuffersLocked(); 197 198 return !acquired_buffers_.IsEmpty() && 199 acquired_buffers_.Front().IsAvailable(); 200} 201 202bool DisplaySurface::IsBufferPosted() { 203 std::lock_guard<std::mutex> autolock(lock_); 204 DequeueBuffersLocked(); 205 206 return !acquired_buffers_.IsEmpty(); 207} 208 209pdx::Status<void> DisplaySurface::HandleMessage(pdx::Message& message) { 210 switch (message.GetOp()) { 211 case DisplayRPC::SetAttributes::Opcode: 212 DispatchRemoteMethod<DisplayRPC::SetAttributes>( 213 *this, &DisplaySurface::OnClientSetAttributes, message); 214 break; 215 216 case DisplayRPC::CreateBufferQueue::Opcode: 217 DispatchRemoteMethod<DisplayRPC::CreateBufferQueue>( 218 *this, &DisplaySurface::OnCreateBufferQueue, message); 219 break; 220 221 case DisplayRPC::CreateVideoMeshSurface::Opcode: 222 DispatchRemoteMethod<DisplayRPC::CreateVideoMeshSurface>( 223 *this, &DisplaySurface::OnCreateVideoMeshSurface, message); 224 break; 225 226 default: 227 return SurfaceChannel::HandleMessage(message); 228 } 229 230 return {}; 231} 232 233int DisplaySurface::OnClientSetAttributes( 234 pdx::Message& /*message*/, const DisplaySurfaceAttributes& attributes) { 235 for (const auto& attribute : attributes) { 236 const auto& key = attribute.first; 237 const auto* variant = &attribute.second; 238 bool invalid_value = false; 239 switch (key) { 240 case DisplaySurfaceAttributeEnum::ZOrder: 241 invalid_value = !IfAnyOf<int32_t, int64_t, float>::Call( 242 variant, [this](const auto& value) { 243 DisplaySurface::ClientSetZOrder(value); 244 }); 245 break; 246 case DisplaySurfaceAttributeEnum::Visible: 247 invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call( 248 variant, [this](const auto& value) { 249 DisplaySurface::ClientSetVisible(value); 250 }); 251 break; 252 case DisplaySurfaceAttributeEnum::ExcludeFromBlur: 253 invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call( 254 variant, [this](const auto& value) { 255 DisplaySurface::ClientSetExcludeFromBlur(value); 256 }); 257 break; 258 case DisplaySurfaceAttributeEnum::BlurBehind: 259 invalid_value = !IfAnyOf<int32_t, int64_t, bool>::Call( 260 variant, [this](const auto& value) { 261 DisplaySurface::ClientSetBlurBehind(value); 262 }); 263 break; 264 default: 265 ALOGW( 266 "DisplaySurface::OnClientSetAttributes: Unrecognized attribute %d " 267 "surface_id=%d", 268 key, surface_id()); 269 break; 270 } 271 272 if (invalid_value) { 273 ALOGW( 274 "DisplaySurface::OnClientSetAttributes: Failed to set display " 275 "surface attribute '%s' because of incompatible type: %d", 276 DisplaySurfaceAttributeEnum::ToString(key).c_str(), variant->index()); 277 } 278 } 279 280 service()->NotifyDisplayConfigurationUpdate(); 281 return 0; 282} 283 284LocalChannelHandle DisplaySurface::OnCreateBufferQueue(Message& message) { 285 ATRACE_NAME("DisplaySurface::OnCreateBufferQueue"); 286 287 if (consumer_queue_ != nullptr) { 288 ALOGE( 289 "DisplaySurface::OnCreateBufferQueue: A ProdcuerQueue has already been " 290 "created and transported to DisplayClient."); 291 REPLY_ERROR_RETURN(message, EALREADY, {}); 292 } 293 294 auto producer = ProducerQueue::Create<uint64_t>(); 295 consumer_queue_ = producer->CreateConsumerQueue(); 296 297 return std::move(producer->GetChannelHandle()); 298} 299 300RemoteChannelHandle DisplaySurface::OnCreateVideoMeshSurface( 301 pdx::Message& message) { 302 if (flags_ & DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION) { 303 ALOGE( 304 "DisplaySurface::OnCreateVideoMeshSurface: system distortion is " 305 "disabled on this display surface, cannot create VideoMeshSurface on " 306 "top of it."); 307 REPLY_ERROR_RETURN(message, EINVAL, {}); 308 } 309 310 int channel_id; 311 auto status = message.PushChannel(0, nullptr, &channel_id); 312 if (!status) { 313 ALOGE( 314 "DisplaySurface::OnCreateVideoMeshSurface: failed to push channel: %s", 315 status.GetErrorMessage().c_str()); 316 REPLY_ERROR_RETURN(message, status.error(), {}); 317 } 318 319 auto surface = std::make_shared<VideoMeshSurface>(service(), channel_id); 320 auto channel_status = service()->SetChannel(channel_id, surface); 321 if (!channel_status) { 322 ALOGE( 323 "DisplaySurface::OnCreateVideoMeshSurface: failed to set new video " 324 "mesh surface channel: %s", 325 channel_status.GetErrorMessage().c_str()); 326 REPLY_ERROR_RETURN(message, channel_status.error(), {}); 327 } 328 329 { 330 std::lock_guard<std::mutex> autolock(lock_); 331 pending_video_mesh_surfaces_.push_back(surface); 332 video_mesh_surfaces_updated_ = true; 333 } 334 335 return status.take(); 336} 337 338std::vector<std::shared_ptr<VideoMeshSurface>> 339DisplaySurface::GetVideoMeshSurfaces() { 340 std::lock_guard<std::mutex> autolock(lock_); 341 std::vector<std::shared_ptr<VideoMeshSurface>> surfaces; 342 343 for (auto& surface : pending_video_mesh_surfaces_) { 344 if (auto video_surface = surface.lock()) { 345 surfaces.push_back(video_surface); 346 } else { 347 ALOGE("Unable to lock video mesh surface."); 348 } 349 } 350 351 pending_video_mesh_surfaces_.clear(); 352 video_mesh_surfaces_updated_ = false; 353 return surfaces; 354} 355 356} // namespace dvr 357} // namespace android 358