OSDN Git Service

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