VirtualDisplaySurface.cpp revision db89edc94bd2a78226b407f9f7261e202e7fa325
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    mProducerUsage(GRALLOC_USAGE_HW_COMPOSER),
51    mProducerSlotSource(0),
52    mDbgState(DBG_STATE_IDLE),
53    mDbgLastCompositionType(COMPOSITION_UNKNOWN)
54{
55    mSource[SOURCE_SINK] = sink;
56    mSource[SOURCE_SCRATCH] = bq;
57
58    resetPerFrameState();
59
60    int sinkWidth, sinkHeight;
61    mSource[SOURCE_SINK]->query(NATIVE_WINDOW_WIDTH, &sinkWidth);
62    mSource[SOURCE_SINK]->query(NATIVE_WINDOW_HEIGHT, &sinkHeight);
63
64    ConsumerBase::mName = String8::format("VDS: %s", mDisplayName.string());
65    mConsumer->setConsumerName(ConsumerBase::mName);
66    mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
67    mConsumer->setDefaultBufferSize(sinkWidth, sinkHeight);
68    mConsumer->setDefaultMaxBufferCount(2);
69}
70
71VirtualDisplaySurface::~VirtualDisplaySurface() {
72}
73
74status_t VirtualDisplaySurface::prepareFrame(CompositionType compositionType) {
75    if (mDisplayId < 0)
76        return NO_ERROR;
77
78    VDS_LOGW_IF(mDbgState != DBG_STATE_IDLE,
79            "Unexpected prepareFrame() in %s state", dbgStateStr());
80    mDbgState = DBG_STATE_PREPARED;
81
82    mCompositionType = compositionType;
83
84    if (mCompositionType != mDbgLastCompositionType) {
85        VDS_LOGV("prepareFrame: composition type changed to %s",
86                dbgCompositionTypeStr(mCompositionType));
87        mDbgLastCompositionType = mCompositionType;
88    }
89
90    return NO_ERROR;
91}
92
93status_t VirtualDisplaySurface::compositionComplete() {
94    return NO_ERROR;
95}
96
97status_t VirtualDisplaySurface::advanceFrame() {
98    if (mDisplayId < 0)
99        return NO_ERROR;
100
101    if (mCompositionType == COMPOSITION_HWC) {
102        VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
103                "Unexpected advanceFrame() in %s state on HWC frame",
104                dbgStateStr());
105    } else {
106        VDS_LOGW_IF(mDbgState != DBG_STATE_GLES_DONE,
107                "Unexpected advanceFrame() in %s state on GLES/MIXED frame",
108                dbgStateStr());
109    }
110    mDbgState = DBG_STATE_HWC;
111
112    status_t result;
113    sp<Fence> outFence;
114    if (mCompositionType != COMPOSITION_GLES) {
115        // Dequeue an output buffer from the sink
116        uint32_t transformHint, numPendingBuffers;
117        mQueueBufferOutput.deflate(&mSinkBufferWidth, &mSinkBufferHeight,
118                &transformHint, &numPendingBuffers);
119        int sslot;
120        result = dequeueBuffer(SOURCE_SINK, 0, &sslot, &outFence, false);
121        if (result < 0)
122            return result;
123        mOutputProducerSlot = mapSource2ProducerSlot(SOURCE_SINK, sslot);
124    }
125
126    if (mCompositionType == COMPOSITION_HWC) {
127        // We just dequeued the output buffer, use it for FB as well
128        mFbProducerSlot = mOutputProducerSlot;
129        mFbFence = outFence;
130    } else if (mCompositionType == COMPOSITION_GLES) {
131        mOutputProducerSlot = mFbProducerSlot;
132        outFence = mFbFence;
133    } else {
134        // mFbFence and mFbProducerSlot were set in queueBuffer,
135        // and mOutputProducerSlot and outFence were set above when dequeueing
136        // the sink buffer.
137    }
138
139    if (mFbProducerSlot < 0 || mOutputProducerSlot < 0) {
140        // Last chance bailout if something bad happened earlier. For example,
141        // in a GLES configuration, if the sink disappears then dequeueBuffer
142        // will fail, the GLES driver won't queue a buffer, but SurfaceFlinger
143        // will soldier on. So we end up here without a buffer. There should
144        // be lots of scary messages in the log just before this.
145        VDS_LOGE("advanceFrame: no buffer, bailing out");
146        return NO_MEMORY;
147    }
148
149    sp<GraphicBuffer> fbBuffer = mProducerBuffers[mFbProducerSlot];
150    sp<GraphicBuffer> outBuffer = mProducerBuffers[mOutputProducerSlot];
151    VDS_LOGV("advanceFrame: fb=%d(%p) out=%d(%p)",
152            mFbProducerSlot, fbBuffer.get(),
153            mOutputProducerSlot, outBuffer.get());
154
155    result = mHwc.fbPost(mDisplayId, mFbFence, fbBuffer);
156    if (result == NO_ERROR) {
157        result = mHwc.setOutputBuffer(mDisplayId, outFence, outBuffer);
158    }
159
160    return result;
161}
162
163void VirtualDisplaySurface::onFrameCommitted() {
164    if (mDisplayId < 0)
165        return;
166
167    VDS_LOGW_IF(mDbgState != DBG_STATE_HWC,
168            "Unexpected onFrameCommitted() in %s state", dbgStateStr());
169    mDbgState = DBG_STATE_IDLE;
170
171    sp<Fence> fbFence = mHwc.getAndResetReleaseFence(mDisplayId);
172    if (mCompositionType == COMPOSITION_MIXED && mFbProducerSlot >= 0) {
173        // release the scratch buffer back to the pool
174        Mutex::Autolock lock(mMutex);
175        int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, mFbProducerSlot);
176        VDS_LOGV("onFrameCommitted: release scratch sslot=%d", sslot);
177        addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot], fbFence);
178        releaseBufferLocked(sslot, mProducerBuffers[mFbProducerSlot],
179                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
180    }
181
182    if (mOutputProducerSlot >= 0) {
183        int sslot = mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot);
184        QueueBufferOutput qbo;
185        sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId);
186        VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot);
187        status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
188                QueueBufferInput(systemTime(),
189                    Rect(mSinkBufferWidth, mSinkBufferHeight),
190                    NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, outFence),
191                &qbo);
192        if (result == NO_ERROR) {
193            updateQueueBufferOutput(qbo);
194        }
195    }
196
197    resetPerFrameState();
198}
199
200void VirtualDisplaySurface::dump(String8& result) const {
201}
202
203status_t VirtualDisplaySurface::requestBuffer(int pslot,
204        sp<GraphicBuffer>* outBuf) {
205    VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
206            "Unexpected requestBuffer pslot=%d in %s state",
207            pslot, dbgStateStr());
208
209    *outBuf = mProducerBuffers[pslot];
210    return NO_ERROR;
211}
212
213status_t VirtualDisplaySurface::setBufferCount(int bufferCount) {
214    return mSource[SOURCE_SINK]->setBufferCount(bufferCount);
215}
216
217status_t VirtualDisplaySurface::dequeueBuffer(Source source,
218        uint32_t format, int* sslot, sp<Fence>* fence, bool async) {
219    status_t result = mSource[source]->dequeueBuffer(sslot, fence, async,
220            mSinkBufferWidth, mSinkBufferHeight, format, mProducerUsage);
221    if (result < 0)
222        return result;
223    int pslot = mapSource2ProducerSlot(source, *sslot);
224    VDS_LOGV("dequeueBuffer(%s): sslot=%d pslot=%d result=%d",
225            dbgSourceStr(source), *sslot, pslot, result);
226    uint32_t sourceBit = static_cast<uint32_t>(source) << pslot;
227
228    if ((mProducerSlotSource & (1u << pslot)) != sourceBit) {
229        // This slot was previously dequeued from the other source; must
230        // re-request the buffer.
231        result |= BUFFER_NEEDS_REALLOCATION;
232        mProducerSlotSource &= ~(1u << pslot);
233        mProducerSlotSource |= sourceBit;
234    }
235
236    if (result & RELEASE_ALL_BUFFERS) {
237        for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
238            if ((mProducerSlotSource & (1u << i)) == sourceBit)
239                mProducerBuffers[i].clear();
240        }
241    }
242    if (result & BUFFER_NEEDS_REALLOCATION) {
243        mSource[source]->requestBuffer(*sslot, &mProducerBuffers[pslot]);
244        VDS_LOGV("dequeueBuffer(%s): buffers[%d]=%p",
245                dbgSourceStr(source), pslot, mProducerBuffers[pslot].get());
246    }
247
248    return result;
249}
250
251status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool async,
252        uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
253    VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
254            "Unexpected dequeueBuffer() in %s state", dbgStateStr());
255    mDbgState = DBG_STATE_GLES;
256
257    VDS_LOGV("dequeueBuffer %dx%d fmt=%d usage=%#x", w, h, format, usage);
258
259    mProducerUsage = usage | GRALLOC_USAGE_HW_COMPOSER;
260    Source source = fbSourceForCompositionType(mCompositionType);
261    if (source == SOURCE_SINK) {
262        mSinkBufferWidth = w;
263        mSinkBufferHeight = h;
264    }
265
266    int sslot;
267    status_t result = dequeueBuffer(source, format, &sslot, fence, async);
268    if (result >= 0) {
269        *pslot = mapSource2ProducerSlot(source, sslot);
270    }
271    return result;
272}
273
274status_t VirtualDisplaySurface::queueBuffer(int pslot,
275        const QueueBufferInput& input, QueueBufferOutput* output) {
276    VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
277            "Unexpected queueBuffer(pslot=%d) in %s state", pslot,
278            dbgStateStr());
279    mDbgState = DBG_STATE_GLES_DONE;
280
281    VDS_LOGV("queueBuffer pslot=%d", pslot);
282
283    status_t result;
284    if (mCompositionType == COMPOSITION_MIXED) {
285        // Queue the buffer back into the scratch pool
286        QueueBufferOutput scratchQBO;
287        int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, pslot);
288        result = mSource[SOURCE_SCRATCH]->queueBuffer(sslot, input, &scratchQBO);
289        if (result != NO_ERROR)
290            return result;
291
292        // Now acquire the buffer from the scratch pool -- should be the same
293        // slot and fence as we just queued.
294        Mutex::Autolock lock(mMutex);
295        BufferQueue::BufferItem item;
296        result = acquireBufferLocked(&item, 0);
297        if (result != NO_ERROR)
298            return result;
299        VDS_LOGW_IF(item.mBuf != sslot,
300                "queueBuffer: acquired sslot %d from SCRATCH after queueing sslot %d",
301                item.mBuf, sslot);
302        mFbProducerSlot = mapSource2ProducerSlot(SOURCE_SCRATCH, item.mBuf);
303        mFbFence = mSlots[item.mBuf].mFence;
304
305    } else {
306        LOG_FATAL_IF(mCompositionType != COMPOSITION_GLES,
307                "Unexpected queueBuffer in state %s for compositionType %s",
308                dbgStateStr(), dbgCompositionTypeStr(mCompositionType));
309
310        // Extract the GLES release fence for HWC to acquire
311        int64_t timestamp;
312        Rect crop;
313        int scalingMode;
314        uint32_t transform;
315        bool async;
316        input.deflate(&timestamp, &crop, &scalingMode, &transform,
317                &async, &mFbFence);
318
319        mFbProducerSlot = pslot;
320    }
321
322    *output = mQueueBufferOutput;
323    return NO_ERROR;
324}
325
326void VirtualDisplaySurface::cancelBuffer(int pslot, const sp<Fence>& fence) {
327    VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
328            "Unexpected cancelBuffer(pslot=%d) in %s state", pslot,
329            dbgStateStr());
330    VDS_LOGV("cancelBuffer pslot=%d", pslot);
331    Source source = fbSourceForCompositionType(mCompositionType);
332    return mSource[source]->cancelBuffer(
333            mapProducer2SourceSlot(source, pslot), fence);
334}
335
336int VirtualDisplaySurface::query(int what, int* value) {
337    return mSource[SOURCE_SINK]->query(what, value);
338}
339
340status_t VirtualDisplaySurface::connect(int api, bool producerControlledByApp,
341        QueueBufferOutput* output) {
342    QueueBufferOutput qbo;
343    status_t result = mSource[SOURCE_SINK]->connect(api, producerControlledByApp, &qbo);
344    if (result == NO_ERROR) {
345        updateQueueBufferOutput(qbo);
346        *output = mQueueBufferOutput;
347    }
348    return result;
349}
350
351status_t VirtualDisplaySurface::disconnect(int api) {
352    return mSource[SOURCE_SINK]->disconnect(api);
353}
354
355void VirtualDisplaySurface::updateQueueBufferOutput(
356        const QueueBufferOutput& qbo) {
357    uint32_t w, h, transformHint, numPendingBuffers;
358    qbo.deflate(&w, &h, &transformHint, &numPendingBuffers);
359    mQueueBufferOutput.inflate(w, h, 0, numPendingBuffers);
360}
361
362void VirtualDisplaySurface::resetPerFrameState() {
363    mCompositionType = COMPOSITION_UNKNOWN;
364    mSinkBufferWidth = 0;
365    mSinkBufferHeight = 0;
366    mFbFence = Fence::NO_FENCE;
367    mFbProducerSlot = -1;
368    mOutputProducerSlot = -1;
369}
370
371// This slot mapping function is its own inverse, so two copies are unnecessary.
372// Both are kept to make the intent clear where the function is called, and for
373// the (unlikely) chance that we switch to a different mapping function.
374int VirtualDisplaySurface::mapSource2ProducerSlot(Source source, int sslot) {
375    if (source == SOURCE_SCRATCH) {
376        return BufferQueue::NUM_BUFFER_SLOTS - sslot - 1;
377    } else {
378        return sslot;
379    }
380}
381int VirtualDisplaySurface::mapProducer2SourceSlot(Source source, int pslot) {
382    return mapSource2ProducerSlot(source, pslot);
383}
384
385VirtualDisplaySurface::Source
386VirtualDisplaySurface::fbSourceForCompositionType(CompositionType type) {
387    return type == COMPOSITION_MIXED ? SOURCE_SCRATCH : SOURCE_SINK;
388}
389
390const char* VirtualDisplaySurface::dbgStateStr() const {
391    switch (mDbgState) {
392        case DBG_STATE_IDLE:      return "IDLE";
393        case DBG_STATE_PREPARED:  return "PREPARED";
394        case DBG_STATE_GLES:      return "GLES";
395        case DBG_STATE_GLES_DONE: return "GLES_DONE";
396        case DBG_STATE_HWC:       return "HWC";
397        default:                  return "INVALID";
398    }
399}
400
401const char* VirtualDisplaySurface::dbgSourceStr(Source s) {
402    switch (s) {
403        case SOURCE_SINK:    return "SINK";
404        case SOURCE_SCRATCH: return "SCRATCH";
405        default:             return "INVALID";
406    }
407}
408
409// ---------------------------------------------------------------------------
410} // namespace android
411// ---------------------------------------------------------------------------
412