OSDN Git Service

89c87c70f04a9929f794a2a1e7a84ddd4bdce515
[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::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
93 status_t VirtualDisplaySurface::compositionComplete() {
94     return NO_ERROR;
95 }
96
97 status_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
163 void 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(), false,
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
200 void VirtualDisplaySurface::dump(String8& result) const {
201 }
202
203 status_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
213 status_t VirtualDisplaySurface::setBufferCount(int bufferCount) {
214     return mSource[SOURCE_SINK]->setBufferCount(bufferCount);
215 }
216
217 status_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
251 status_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
274 status_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         bool isAutoTimestamp;
313         Rect crop;
314         int scalingMode;
315         uint32_t transform;
316         bool async;
317         input.deflate(&timestamp, &isAutoTimestamp, &crop, &scalingMode,
318                 &transform, &async, &mFbFence);
319
320         mFbProducerSlot = pslot;
321     }
322
323     *output = mQueueBufferOutput;
324     return NO_ERROR;
325 }
326
327 void VirtualDisplaySurface::cancelBuffer(int pslot, const sp<Fence>& fence) {
328     VDS_LOGW_IF(mDbgState != DBG_STATE_GLES,
329             "Unexpected cancelBuffer(pslot=%d) in %s state", pslot,
330             dbgStateStr());
331     VDS_LOGV("cancelBuffer pslot=%d", pslot);
332     Source source = fbSourceForCompositionType(mCompositionType);
333     return mSource[source]->cancelBuffer(
334             mapProducer2SourceSlot(source, pslot), fence);
335 }
336
337 int VirtualDisplaySurface::query(int what, int* value) {
338     return mSource[SOURCE_SINK]->query(what, value);
339 }
340
341 status_t VirtualDisplaySurface::connect(int api, bool producerControlledByApp,
342         QueueBufferOutput* output) {
343     QueueBufferOutput qbo;
344     status_t result = mSource[SOURCE_SINK]->connect(api, producerControlledByApp, &qbo);
345     if (result == NO_ERROR) {
346         updateQueueBufferOutput(qbo);
347         *output = mQueueBufferOutput;
348     }
349     return result;
350 }
351
352 status_t VirtualDisplaySurface::disconnect(int api) {
353     return mSource[SOURCE_SINK]->disconnect(api);
354 }
355
356 void VirtualDisplaySurface::updateQueueBufferOutput(
357         const QueueBufferOutput& qbo) {
358     uint32_t w, h, transformHint, numPendingBuffers;
359     qbo.deflate(&w, &h, &transformHint, &numPendingBuffers);
360     mQueueBufferOutput.inflate(w, h, 0, numPendingBuffers);
361 }
362
363 void VirtualDisplaySurface::resetPerFrameState() {
364     mCompositionType = COMPOSITION_UNKNOWN;
365     mSinkBufferWidth = 0;
366     mSinkBufferHeight = 0;
367     mFbFence = Fence::NO_FENCE;
368     mFbProducerSlot = -1;
369     mOutputProducerSlot = -1;
370 }
371
372 // This slot mapping function is its own inverse, so two copies are unnecessary.
373 // Both are kept to make the intent clear where the function is called, and for
374 // the (unlikely) chance that we switch to a different mapping function.
375 int VirtualDisplaySurface::mapSource2ProducerSlot(Source source, int sslot) {
376     if (source == SOURCE_SCRATCH) {
377         return BufferQueue::NUM_BUFFER_SLOTS - sslot - 1;
378     } else {
379         return sslot;
380     }
381 }
382 int VirtualDisplaySurface::mapProducer2SourceSlot(Source source, int pslot) {
383     return mapSource2ProducerSlot(source, pslot);
384 }
385
386 VirtualDisplaySurface::Source
387 VirtualDisplaySurface::fbSourceForCompositionType(CompositionType type) {
388     return type == COMPOSITION_MIXED ? SOURCE_SCRATCH : SOURCE_SINK;
389 }
390
391 const char* VirtualDisplaySurface::dbgStateStr() const {
392     switch (mDbgState) {
393         case DBG_STATE_IDLE:      return "IDLE";
394         case DBG_STATE_PREPARED:  return "PREPARED";
395         case DBG_STATE_GLES:      return "GLES";
396         case DBG_STATE_GLES_DONE: return "GLES_DONE";
397         case DBG_STATE_HWC:       return "HWC";
398         default:                  return "INVALID";
399     }
400 }
401
402 const char* VirtualDisplaySurface::dbgSourceStr(Source s) {
403     switch (s) {
404         case SOURCE_SINK:    return "SINK";
405         case SOURCE_SCRATCH: return "SCRATCH";
406         default:             return "INVALID";
407     }
408 }
409
410 // ---------------------------------------------------------------------------
411 } // namespace android
412 // ---------------------------------------------------------------------------