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