VirtualDisplaySurface.cpp revision 1e27ba234c5bfd4f6535ee221a6c20407a50f868
1/* 2 * Copyright 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17// #define LOG_NDEBUG 0 18#include "VirtualDisplaySurface.h" 19#include "HWComposer.h" 20 21// --------------------------------------------------------------------------- 22namespace android { 23// --------------------------------------------------------------------------- 24 25#define VDS_LOGE(msg, ...) ALOGE("[%s] "msg, \ 26 mDisplayName.string(), ##__VA_ARGS__) 27#define VDS_LOGW_IF(cond, msg, ...) ALOGW_IF(cond, "[%s] "msg, \ 28 mDisplayName.string(), ##__VA_ARGS__) 29#define VDS_LOGV(msg, ...) ALOGV("[%s] "msg, \ 30 mDisplayName.string(), ##__VA_ARGS__) 31 32static const char* dbgCompositionTypeStr(DisplaySurface::CompositionType type) { 33 switch (type) { 34 case DisplaySurface::COMPOSITION_UNKNOWN: return "UNKNOWN"; 35 case DisplaySurface::COMPOSITION_GLES: return "GLES"; 36 case DisplaySurface::COMPOSITION_HWC: return "HWC"; 37 case DisplaySurface::COMPOSITION_MIXED: return "MIXED"; 38 default: return "<INVALID>"; 39 } 40} 41 42VirtualDisplaySurface::VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, 43 const sp<IGraphicBufferProducer>& sink, 44 const sp<BufferQueue>& bq, 45 const String8& name) 46: ConsumerBase(bq), 47 mHwc(hwc), 48 mDisplayId(dispId), 49 mDisplayName(name), 50 mOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED), 51 mOutputUsage(GRALLOC_USAGE_HW_COMPOSER), 52 mProducerSlotSource(0), 53 mDbgState(DBG_STATE_IDLE), 54 mDbgLastCompositionType(COMPOSITION_UNKNOWN) 55{ 56 mSource[SOURCE_SINK] = sink; 57 mSource[SOURCE_SCRATCH] = bq; 58 59 resetPerFrameState(); 60 61 int sinkWidth, sinkHeight; 62 mSource[SOURCE_SINK]->query(NATIVE_WINDOW_WIDTH, &sinkWidth); 63 mSource[SOURCE_SINK]->query(NATIVE_WINDOW_HEIGHT, &sinkHeight); 64 65 ConsumerBase::mName = String8::format("VDS: %s", mDisplayName.string()); 66 mConsumer->setConsumerName(ConsumerBase::mName); 67 mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER); 68 mConsumer->setDefaultBufferSize(sinkWidth, sinkHeight); 69 mConsumer->setDefaultMaxBufferCount(2); 70} 71 72VirtualDisplaySurface::~VirtualDisplaySurface() { 73} 74 75status_t VirtualDisplaySurface::beginFrame() { 76 if (mDisplayId < 0) 77 return NO_ERROR; 78 79 VDS_LOGW_IF(mDbgState != DBG_STATE_IDLE, 80 "Unexpected beginFrame() in %s state", dbgStateStr()); 81 mDbgState = DBG_STATE_BEGUN; 82 83 uint32_t transformHint, numPendingBuffers; 84 mQueueBufferOutput.deflate(&mSinkBufferWidth, &mSinkBufferHeight, 85 &transformHint, &numPendingBuffers); 86 87 return refreshOutputBuffer(); 88} 89 90status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) { 91 if (mDisplayId < 0) 92 return NO_ERROR; 93 94 VDS_LOGW_IF(mDbgState != DBG_STATE_BEGUN, 95 "Unexpected prepareFrame() in %s state", dbgStateStr()); 96 mDbgState = DBG_STATE_PREPARED; 97 98 mCompositionType = compositionType; 99 if (mCompositionType != mDbgLastCompositionType) { 100 VDS_LOGV("prepareFrame: composition type changed to %s", 101 dbgCompositionTypeStr(mCompositionType)); 102 mDbgLastCompositionType = mCompositionType; 103 } 104 105 if (mCompositionType != COMPOSITION_GLES && 106 (mOutputFormat != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED || 107 mOutputUsage != GRALLOC_USAGE_HW_COMPOSER)) { 108 // We must have just switched from GLES-only to MIXED or HWC 109 // composition. Stop using the format and usage requested by the GLES 110 // driver; they may be suboptimal when HWC is writing to the output 111 // buffer. For example, if the output is going to a video encoder, and 112 // HWC can write directly to YUV, some hardware can skip a 113 // memory-to-memory RGB-to-YUV conversion step. 114 // 115 // If we just switched *to* GLES-only mode, we'll change the 116 // format/usage and get a new buffer when the GLES driver calls 117 // dequeueBuffer(). 118 mOutputFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; 119 mOutputUsage = GRALLOC_USAGE_HW_COMPOSER; 120 refreshOutputBuffer(); 121 } 122 123 return NO_ERROR; 124} 125 126status_t VirtualDisplaySurface::compositionComplete() { 127 return NO_ERROR; 128} 129 130status_t VirtualDisplaySurface::advanceFrame() { 131 if (mDisplayId < 0) 132 return NO_ERROR; 133 134 if (mCompositionType == COMPOSITION_HWC) { 135 VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED, 136 "Unexpected advanceFrame() in %s state on HWC frame", 137 dbgStateStr()); 138 } else { 139 VDS_LOGW_IF(mDbgState != DBG_STATE_GLES_DONE, 140 "Unexpected advanceFrame() in %s state on GLES/MIXED frame", 141 dbgStateStr()); 142 } 143 mDbgState = DBG_STATE_HWC; 144 145 if (mCompositionType == COMPOSITION_HWC) { 146 // Use the output buffer for the FB as well, though conceptually the 147 // FB is unused on this frame. 148 mFbProducerSlot = mOutputProducerSlot; 149 mFbFence = mOutputFence; 150 } 151 152 if (mFbProducerSlot < 0 || mOutputProducerSlot < 0) { 153 // Last chance bailout if something bad happened earlier. For example, 154 // in a GLES configuration, if the sink disappears then dequeueBuffer 155 // will fail, the GLES driver won't queue a buffer, but SurfaceFlinger 156 // will soldier on. So we end up here without a buffer. There should 157 // be lots of scary messages in the log just before this. 158 VDS_LOGE("advanceFrame: no buffer, bailing out"); 159 return NO_MEMORY; 160 } 161 162 sp<GraphicBuffer> fbBuffer = mProducerBuffers[mFbProducerSlot]; 163 sp<GraphicBuffer> outBuffer = mProducerBuffers[mOutputProducerSlot]; 164 VDS_LOGV("advanceFrame: fb=%d(%p) out=%d(%p)", 165 mFbProducerSlot, fbBuffer.get(), 166 mOutputProducerSlot, outBuffer.get()); 167 168 // At this point we know the output buffer acquire fence, 169 // so update HWC state with it. 170 mHwc.setOutputBuffer(mDisplayId, mOutputFence, outBuffer); 171 172 return mHwc.fbPost(mDisplayId, mFbFence, fbBuffer); 173} 174 175void VirtualDisplaySurface::onFrameCommitted() { 176 if (mDisplayId < 0) 177 return; 178 179 VDS_LOGW_IF(mDbgState != DBG_STATE_HWC, 180 "Unexpected onFrameCommitted() in %s state", dbgStateStr()); 181 mDbgState = DBG_STATE_IDLE; 182 183 sp<Fence> fbFence = mHwc.getAndResetReleaseFence(mDisplayId); 184 if (mCompositionType == COMPOSITION_MIXED && mFbProducerSlot >= 0) { 185 // release the scratch buffer back to the pool 186 Mutex::Autolock lock(mMutex); 187 int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, mFbProducerSlot); 188 VDS_LOGV("onFrameCommitted: release scratch sslot=%d", sslot); 189 addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot], fbFence); 190 releaseBufferLocked(sslot, mProducerBuffers[mFbProducerSlot], 191 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR); 192 } 193 194 if (mOutputProducerSlot >= 0) { 195 int sslot = mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot); 196 QueueBufferOutput qbo; 197 sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId); 198 VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot); 199 status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot, 200 QueueBufferInput( 201 systemTime(), false /* isAutoTimestamp */, 202 Rect(mSinkBufferWidth, mSinkBufferHeight), 203 NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */, 204 true /* async*/, 205 outFence), 206 &qbo); 207 if (result == NO_ERROR) { 208 updateQueueBufferOutput(qbo); 209 } 210 } 211 212 resetPerFrameState(); 213} 214 215void VirtualDisplaySurface::dump(String8& result) const { 216} 217 218status_t VirtualDisplaySurface::requestBuffer(int pslot, 219 sp<GraphicBuffer>* outBuf) { 220 VDS_LOGW_IF(mDbgState != DBG_STATE_GLES, 221 "Unexpected requestBuffer pslot=%d in %s state", 222 pslot, dbgStateStr()); 223 224 *outBuf = mProducerBuffers[pslot]; 225 return NO_ERROR; 226} 227 228status_t VirtualDisplaySurface::setBufferCount(int bufferCount) { 229 return mSource[SOURCE_SINK]->setBufferCount(bufferCount); 230} 231 232status_t VirtualDisplaySurface::dequeueBuffer(Source source, 233 uint32_t format, uint32_t usage, int* sslot, sp<Fence>* fence) { 234 // Don't let a slow consumer block us 235 bool async = (source == SOURCE_SINK); 236 237 status_t result = mSource[source]->dequeueBuffer(sslot, fence, async, 238 mSinkBufferWidth, mSinkBufferHeight, format, usage); 239 if (result < 0) 240 return result; 241 int pslot = mapSource2ProducerSlot(source, *sslot); 242 VDS_LOGV("dequeueBuffer(%s): sslot=%d pslot=%d result=%d", 243 dbgSourceStr(source), *sslot, pslot, result); 244 uint32_t sourceBit = static_cast<uint32_t>(source) << pslot; 245 246 if ((mProducerSlotSource & (1u << pslot)) != sourceBit) { 247 // This slot was previously dequeued from the other source; must 248 // re-request the buffer. 249 result |= BUFFER_NEEDS_REALLOCATION; 250 mProducerSlotSource &= ~(1u << pslot); 251 mProducerSlotSource |= sourceBit; 252 } 253 254 if (result & RELEASE_ALL_BUFFERS) { 255 for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) { 256 if ((mProducerSlotSource & (1u << i)) == sourceBit) 257 mProducerBuffers[i].clear(); 258 } 259 } 260 if (result & BUFFER_NEEDS_REALLOCATION) { 261 mSource[source]->requestBuffer(*sslot, &mProducerBuffers[pslot]); 262 VDS_LOGV("dequeueBuffer(%s): buffers[%d]=%p", 263 dbgSourceStr(source), pslot, mProducerBuffers[pslot].get()); 264 } 265 266 return result; 267} 268 269status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool async, 270 uint32_t w, uint32_t h, uint32_t format, uint32_t usage) { 271 VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED, 272 "Unexpected dequeueBuffer() in %s state", dbgStateStr()); 273 mDbgState = DBG_STATE_GLES; 274 275 VDS_LOGW_IF(!async, "EGL called dequeueBuffer with !async despite eglSwapInterval(0)"); 276 VDS_LOGV("dequeueBuffer %dx%d fmt=%d usage=%#x", w, h, format, usage); 277 278 status_t result = NO_ERROR; 279 Source source = fbSourceForCompositionType(mCompositionType); 280 281 if (source == SOURCE_SINK) { 282 283 if (mOutputProducerSlot < 0) { 284 // Last chance bailout if something bad happened earlier. For example, 285 // in a GLES configuration, if the sink disappears then dequeueBuffer 286 // will fail, the GLES driver won't queue a buffer, but SurfaceFlinger 287 // will soldier on. So we end up here without a buffer. There should 288 // be lots of scary messages in the log just before this. 289 VDS_LOGE("dequeueBuffer: no buffer, bailing out"); 290 return NO_MEMORY; 291 } 292 293 // We already dequeued the output buffer. If the GLES driver wants 294 // something incompatible, we have to cancel and get a new one. This 295 // will mean that HWC will see a different output buffer between 296 // prepare and set, but since we're in GLES-only mode already it 297 // shouldn't matter. 298 299 usage |= GRALLOC_USAGE_HW_COMPOSER; 300 const sp<GraphicBuffer>& buf = mProducerBuffers[mOutputProducerSlot]; 301 if ((usage & ~buf->getUsage()) != 0 || 302 (format != 0 && format != (uint32_t)buf->getPixelFormat()) || 303 (w != 0 && w != mSinkBufferWidth) || 304 (h != 0 && h != mSinkBufferHeight)) { 305 VDS_LOGV("dequeueBuffer: dequeueing new output buffer: " 306 "want %dx%d fmt=%d use=%#x, " 307 "have %dx%d fmt=%d use=%#x", 308 w, h, format, usage, 309 mSinkBufferWidth, mSinkBufferHeight, 310 buf->getPixelFormat(), buf->getUsage()); 311 mOutputFormat = format; 312 mOutputUsage = usage; 313 result = refreshOutputBuffer(); 314 if (result < 0) 315 return result; 316 } 317 } 318 319 if (source == SOURCE_SINK) { 320 *pslot = mOutputProducerSlot; 321 *fence = mOutputFence; 322 } else { 323 int sslot; 324 result = dequeueBuffer(source, format, usage, &sslot, fence); 325 if (result >= 0) { 326 *pslot = mapSource2ProducerSlot(source, sslot); 327 } 328 } 329 return result; 330} 331 332status_t VirtualDisplaySurface::queueBuffer(int pslot, 333 const QueueBufferInput& input, QueueBufferOutput* output) { 334 VDS_LOGW_IF(mDbgState != DBG_STATE_GLES, 335 "Unexpected queueBuffer(pslot=%d) in %s state", pslot, 336 dbgStateStr()); 337 mDbgState = DBG_STATE_GLES_DONE; 338 339 VDS_LOGV("queueBuffer pslot=%d", pslot); 340 341 status_t result; 342 if (mCompositionType == COMPOSITION_MIXED) { 343 // Queue the buffer back into the scratch pool 344 QueueBufferOutput scratchQBO; 345 int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, pslot); 346 result = mSource[SOURCE_SCRATCH]->queueBuffer(sslot, input, &scratchQBO); 347 if (result != NO_ERROR) 348 return result; 349 350 // Now acquire the buffer from the scratch pool -- should be the same 351 // slot and fence as we just queued. 352 Mutex::Autolock lock(mMutex); 353 BufferQueue::BufferItem item; 354 result = acquireBufferLocked(&item, 0); 355 if (result != NO_ERROR) 356 return result; 357 VDS_LOGW_IF(item.mBuf != sslot, 358 "queueBuffer: acquired sslot %d from SCRATCH after queueing sslot %d", 359 item.mBuf, sslot); 360 mFbProducerSlot = mapSource2ProducerSlot(SOURCE_SCRATCH, item.mBuf); 361 mFbFence = mSlots[item.mBuf].mFence; 362 363 } else { 364 LOG_FATAL_IF(mCompositionType != COMPOSITION_GLES, 365 "Unexpected queueBuffer in state %s for compositionType %s", 366 dbgStateStr(), dbgCompositionTypeStr(mCompositionType)); 367 368 // Extract the GLES release fence for HWC to acquire 369 int64_t timestamp; 370 bool isAutoTimestamp; 371 Rect crop; 372 int scalingMode; 373 uint32_t transform; 374 bool async; 375 input.deflate(×tamp, &isAutoTimestamp, &crop, &scalingMode, 376 &transform, &async, &mFbFence); 377 378 mFbProducerSlot = pslot; 379 mOutputFence = mFbFence; 380 } 381 382 *output = mQueueBufferOutput; 383 return NO_ERROR; 384} 385 386void VirtualDisplaySurface::cancelBuffer(int pslot, const sp<Fence>& fence) { 387 VDS_LOGW_IF(mDbgState != DBG_STATE_GLES, 388 "Unexpected cancelBuffer(pslot=%d) in %s state", pslot, 389 dbgStateStr()); 390 VDS_LOGV("cancelBuffer pslot=%d", pslot); 391 Source source = fbSourceForCompositionType(mCompositionType); 392 return mSource[source]->cancelBuffer( 393 mapProducer2SourceSlot(source, pslot), fence); 394} 395 396int VirtualDisplaySurface::query(int what, int* value) { 397 return mSource[SOURCE_SINK]->query(what, value); 398} 399 400status_t VirtualDisplaySurface::connect(const sp<IBinder>& token, 401 int api, bool producerControlledByApp, 402 QueueBufferOutput* output) { 403 QueueBufferOutput qbo; 404 status_t result = mSource[SOURCE_SINK]->connect(token, api, producerControlledByApp, &qbo); 405 if (result == NO_ERROR) { 406 updateQueueBufferOutput(qbo); 407 *output = mQueueBufferOutput; 408 } 409 return result; 410} 411 412status_t VirtualDisplaySurface::disconnect(int api) { 413 return mSource[SOURCE_SINK]->disconnect(api); 414} 415 416void VirtualDisplaySurface::updateQueueBufferOutput( 417 const QueueBufferOutput& qbo) { 418 uint32_t w, h, transformHint, numPendingBuffers; 419 qbo.deflate(&w, &h, &transformHint, &numPendingBuffers); 420 mQueueBufferOutput.inflate(w, h, 0, numPendingBuffers); 421} 422 423void VirtualDisplaySurface::resetPerFrameState() { 424 mCompositionType = COMPOSITION_UNKNOWN; 425 mSinkBufferWidth = 0; 426 mSinkBufferHeight = 0; 427 mFbFence = Fence::NO_FENCE; 428 mOutputFence = Fence::NO_FENCE; 429 mFbProducerSlot = -1; 430 mOutputProducerSlot = -1; 431} 432 433status_t VirtualDisplaySurface::refreshOutputBuffer() { 434 if (mOutputProducerSlot >= 0) { 435 mSource[SOURCE_SINK]->cancelBuffer( 436 mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot), 437 mOutputFence); 438 } 439 440 int sslot; 441 status_t result = dequeueBuffer(SOURCE_SINK, mOutputFormat, mOutputUsage, 442 &sslot, &mOutputFence); 443 if (result < 0) 444 return result; 445 mOutputProducerSlot = mapSource2ProducerSlot(SOURCE_SINK, sslot); 446 447 // On GLES-only frames, we don't have the right output buffer acquire fence 448 // until after GLES calls queueBuffer(). So here we just set the buffer 449 // (for use in HWC prepare) but not the fence; we'll call this again with 450 // the proper fence once we have it. 451 result = mHwc.setOutputBuffer(mDisplayId, Fence::NO_FENCE, 452 mProducerBuffers[mOutputProducerSlot]); 453 454 return result; 455} 456 457// This slot mapping function is its own inverse, so two copies are unnecessary. 458// Both are kept to make the intent clear where the function is called, and for 459// the (unlikely) chance that we switch to a different mapping function. 460int VirtualDisplaySurface::mapSource2ProducerSlot(Source source, int sslot) { 461 if (source == SOURCE_SCRATCH) { 462 return BufferQueue::NUM_BUFFER_SLOTS - sslot - 1; 463 } else { 464 return sslot; 465 } 466} 467int VirtualDisplaySurface::mapProducer2SourceSlot(Source source, int pslot) { 468 return mapSource2ProducerSlot(source, pslot); 469} 470 471VirtualDisplaySurface::Source 472VirtualDisplaySurface::fbSourceForCompositionType(CompositionType type) { 473 return type == COMPOSITION_MIXED ? SOURCE_SCRATCH : SOURCE_SINK; 474} 475 476const char* VirtualDisplaySurface::dbgStateStr() const { 477 switch (mDbgState) { 478 case DBG_STATE_IDLE: return "IDLE"; 479 case DBG_STATE_PREPARED: return "PREPARED"; 480 case DBG_STATE_GLES: return "GLES"; 481 case DBG_STATE_GLES_DONE: return "GLES_DONE"; 482 case DBG_STATE_HWC: return "HWC"; 483 default: return "INVALID"; 484 } 485} 486 487const char* VirtualDisplaySurface::dbgSourceStr(Source s) { 488 switch (s) { 489 case SOURCE_SINK: return "SINK"; 490 case SOURCE_SCRATCH: return "SCRATCH"; 491 default: return "INVALID"; 492 } 493} 494 495// --------------------------------------------------------------------------- 496} // namespace android 497// --------------------------------------------------------------------------- 498