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