Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 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 | #ifndef ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H |
| 18 | #define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H |
| 19 | |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 20 | #include <gui/ConsumerBase.h> |
| 21 | #include <gui/IGraphicBufferProducer.h> |
| 22 | |
Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 23 | #include "DisplaySurface.h" |
| 24 | |
| 25 | // --------------------------------------------------------------------------- |
| 26 | namespace android { |
| 27 | // --------------------------------------------------------------------------- |
| 28 | |
| 29 | class HWComposer; |
Dan Stoza | f0eaf25 | 2014-03-21 13:05:51 -0700 | [diff] [blame] | 30 | class IProducerListener; |
Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 31 | |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 32 | /* This DisplaySurface implementation supports virtual displays, where GLES |
| 33 | * and/or HWC compose into a buffer that is then passed to an arbitrary |
| 34 | * consumer (the sink) running in another process. |
| 35 | * |
| 36 | * The simplest case is when the virtual display will never use the h/w |
| 37 | * composer -- either the h/w composer doesn't support writing to buffers, or |
| 38 | * there are more virtual displays than it supports simultaneously. In this |
| 39 | * case, the GLES driver works directly with the output buffer queue, and |
| 40 | * calls to the VirtualDisplay from SurfaceFlinger and DisplayHardware do |
| 41 | * nothing. |
| 42 | * |
| 43 | * If h/w composer might be used, then each frame will fall into one of three |
| 44 | * configurations: GLES-only, HWC-only, and MIXED composition. In all of these, |
| 45 | * we must provide a FB target buffer and output buffer for the HWC set() call. |
| 46 | * |
| 47 | * In GLES-only composition, the GLES driver is given a buffer from the sink to |
| 48 | * render into. When the GLES driver queues the buffer to the |
| 49 | * VirtualDisplaySurface, the VirtualDisplaySurface holds onto it instead of |
| 50 | * immediately queueing it to the sink. The buffer is used as both the FB |
| 51 | * target and output buffer for HWC, though on these frames the HWC doesn't |
| 52 | * do any work for this display and doesn't write to the output buffer. After |
| 53 | * composition is complete, the buffer is queued to the sink. |
| 54 | * |
| 55 | * In HWC-only composition, the VirtualDisplaySurface dequeues a buffer from |
| 56 | * the sink and passes it to HWC as both the FB target buffer and output |
| 57 | * buffer. The HWC doesn't need to read from the FB target buffer, but does |
| 58 | * write to the output buffer. After composition is complete, the buffer is |
| 59 | * queued to the sink. |
| 60 | * |
| 61 | * On MIXED frames, things become more complicated, since some h/w composer |
| 62 | * implementations can't read from and write to the same buffer. This class has |
| 63 | * an internal BufferQueue that it uses as a scratch buffer pool. The GLES |
| 64 | * driver is given a scratch buffer to render into. When it finishes rendering, |
| 65 | * the buffer is queued and then immediately acquired by the |
| 66 | * VirtualDisplaySurface. The scratch buffer is then used as the FB target |
| 67 | * buffer for HWC, and a separate buffer is dequeued from the sink and used as |
| 68 | * the HWC output buffer. When HWC composition is complete, the scratch buffer |
| 69 | * is released and the output buffer is queued to the sink. |
Jesse Hall | 80e0a39 | 2013-03-15 12:32:10 -0700 | [diff] [blame] | 70 | */ |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 71 | class VirtualDisplaySurface : public DisplaySurface, |
Mathias Agopian | db89edc | 2013-08-02 01:40:18 -0700 | [diff] [blame] | 72 | public BnGraphicBufferProducer, |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 73 | private ConsumerBase { |
Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 74 | public: |
Jesse Hall | ffe1f19 | 2013-03-22 15:13:48 -0700 | [diff] [blame] | 75 | VirtualDisplaySurface(HWComposer& hwc, int32_t dispId, |
Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 76 | const sp<IGraphicBufferProducer>& sink, |
Dan Stoza | b9b0883 | 2014-03-13 11:55:57 -0700 | [diff] [blame] | 77 | const sp<IGraphicBufferProducer>& bqProducer, |
| 78 | const sp<IGraphicBufferConsumer>& bqConsumer, |
Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 79 | const String8& name); |
| 80 | |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 81 | // |
| 82 | // DisplaySurface interface |
| 83 | // |
Dan Stoza | 7143316 | 2014-02-04 16:22:36 -0800 | [diff] [blame] | 84 | virtual status_t beginFrame(bool mustRecompose); |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 85 | virtual status_t prepareFrame(CompositionType compositionType); |
Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 86 | virtual status_t compositionComplete(); |
| 87 | virtual status_t advanceFrame(); |
Jesse Hall | 851cfe8 | 2013-03-20 13:44:00 -0700 | [diff] [blame] | 88 | virtual void onFrameCommitted(); |
Dan Stoza | 01049c8 | 2014-11-11 10:32:31 -0800 | [diff] [blame] | 89 | virtual void dumpAsString(String8& result) const; |
Michael Lentine | 47e4540 | 2014-07-18 15:34:25 -0700 | [diff] [blame] | 90 | virtual void resizeBuffers(const uint32_t w, const uint32_t h); |
Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 91 | |
| 92 | private: |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 93 | enum Source {SOURCE_SINK = 0, SOURCE_SCRATCH = 1}; |
| 94 | |
Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 95 | virtual ~VirtualDisplaySurface(); |
| 96 | |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 97 | // |
| 98 | // IGraphicBufferProducer interface, used by the GLES driver. |
| 99 | // |
| 100 | virtual status_t requestBuffer(int pslot, sp<GraphicBuffer>* outBuf); |
| 101 | virtual status_t setBufferCount(int bufferCount); |
Mathias Agopian | 7cdd786 | 2013-07-18 22:10:56 -0700 | [diff] [blame] | 102 | virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, bool async, |
Dan Stoza | 3be1c6b | 2014-11-18 10:24:03 -0800 | [diff] [blame] | 103 | uint32_t w, uint32_t h, PixelFormat format, uint32_t usage); |
Dan Stoza | 9f3053d | 2014-03-06 15:14:33 -0800 | [diff] [blame] | 104 | virtual status_t detachBuffer(int slot); |
Dan Stoza | d9822a3 | 2014-03-28 15:25:31 -0700 | [diff] [blame] | 105 | virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, |
| 106 | sp<Fence>* outFence); |
Dan Stoza | 9f3053d | 2014-03-06 15:14:33 -0800 | [diff] [blame] | 107 | virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer); |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 108 | virtual status_t queueBuffer(int pslot, |
| 109 | const QueueBufferInput& input, QueueBufferOutput* output); |
| 110 | virtual void cancelBuffer(int pslot, const sp<Fence>& fence); |
| 111 | virtual int query(int what, int* value); |
Dan Stoza | f0eaf25 | 2014-03-21 13:05:51 -0700 | [diff] [blame] | 112 | virtual status_t connect(const sp<IProducerListener>& listener, |
Mathias Agopian | 365857d | 2013-09-11 19:35:45 -0700 | [diff] [blame] | 113 | int api, bool producerControlledByApp, QueueBufferOutput* output); |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 114 | virtual status_t disconnect(int api); |
Jesse Hall | 399184a | 2014-03-03 15:42:54 -0800 | [diff] [blame] | 115 | virtual status_t setSidebandStream(const sp<NativeHandle>& stream); |
Dan Stoza | 29a3e90 | 2014-06-20 13:13:57 -0700 | [diff] [blame] | 116 | virtual void allocateBuffers(bool async, uint32_t width, uint32_t height, |
Dan Stoza | 3be1c6b | 2014-11-18 10:24:03 -0800 | [diff] [blame] | 117 | PixelFormat format, uint32_t usage); |
Dan Stoza | 9de7293 | 2015-04-16 17:28:43 -0700 | [diff] [blame] | 118 | virtual status_t allowAllocation(bool allow); |
Dan Stoza | 812ed06 | 2015-06-02 15:45:22 -0700 | [diff] [blame] | 119 | virtual status_t setGenerationNumber(uint32_t generationNumber); |
Dan Stoza | c6f30bd | 2015-06-08 09:32:50 -0700 | [diff] [blame^] | 120 | virtual String8 getConsumerName() const override; |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 121 | |
| 122 | // |
| 123 | // Utility methods |
| 124 | // |
| 125 | static Source fbSourceForCompositionType(CompositionType type); |
Dan Stoza | 3be1c6b | 2014-11-18 10:24:03 -0800 | [diff] [blame] | 126 | status_t dequeueBuffer(Source source, PixelFormat format, uint32_t usage, |
Jesse Hall | 8db9255 | 2013-08-29 16:03:50 -0700 | [diff] [blame] | 127 | int* sslot, sp<Fence>* fence); |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 128 | void updateQueueBufferOutput(const QueueBufferOutput& qbo); |
| 129 | void resetPerFrameState(); |
Jesse Hall | 028dc8f | 2013-08-20 16:35:32 -0700 | [diff] [blame] | 130 | status_t refreshOutputBuffer(); |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 131 | |
| 132 | // Both the sink and scratch buffer pools have their own set of slots |
| 133 | // ("source slots", or "sslot"). We have to merge these into the single |
| 134 | // set of slots used by the GLES producer ("producer slots" or "pslot") and |
| 135 | // internally in the VirtualDisplaySurface. To minimize the number of times |
| 136 | // a producer slot switches which source it comes from, we map source slot |
| 137 | // numbers to producer slot numbers differently for each source. |
| 138 | static int mapSource2ProducerSlot(Source source, int sslot); |
| 139 | static int mapProducer2SourceSlot(Source source, int pslot); |
| 140 | |
| 141 | // |
| 142 | // Immutable after construction |
| 143 | // |
| 144 | HWComposer& mHwc; |
| 145 | const int32_t mDisplayId; |
| 146 | const String8 mDisplayName; |
| 147 | sp<IGraphicBufferProducer> mSource[2]; // indexed by SOURCE_* |
Jesse Hall | 497ba0e | 2013-11-04 16:43:03 -0800 | [diff] [blame] | 148 | uint32_t mDefaultOutputFormat; |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 149 | |
| 150 | // |
| 151 | // Inter-frame state |
| 152 | // |
| 153 | |
Jesse Hall | 1e27ba2 | 2013-09-27 09:05:09 -0700 | [diff] [blame] | 154 | // To avoid buffer reallocations, we track the buffer usage and format |
| 155 | // we used on the previous frame and use it again on the new frame. If |
| 156 | // the composition type changes or the GLES driver starts requesting |
| 157 | // different usage/format, we'll get a new buffer. |
| 158 | uint32_t mOutputFormat; |
| 159 | uint32_t mOutputUsage; |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 160 | |
| 161 | // Since we present a single producer interface to the GLES driver, but |
| 162 | // are internally muxing between the sink and scratch producers, we have |
| 163 | // to keep track of which source last returned each producer slot from |
Dan Stoza | febd4f4 | 2014-04-09 16:14:51 -0700 | [diff] [blame] | 164 | // dequeueBuffer. Each bit in mProducerSlotSource corresponds to a producer |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 165 | // slot. Both mProducerSlotSource and mProducerBuffers are indexed by a |
| 166 | // "producer slot"; see the mapSlot*() functions. |
Dan Stoza | febd4f4 | 2014-04-09 16:14:51 -0700 | [diff] [blame] | 167 | uint64_t mProducerSlotSource; |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 168 | sp<GraphicBuffer> mProducerBuffers[BufferQueue::NUM_BUFFER_SLOTS]; |
| 169 | |
| 170 | // The QueueBufferOutput with the latest info from the sink, and with the |
| 171 | // transform hint cleared. Since we defer queueBuffer from the GLES driver |
| 172 | // to the sink, we have to return the previous version. |
| 173 | QueueBufferOutput mQueueBufferOutput; |
| 174 | |
Michael Lentine | 47e4540 | 2014-07-18 15:34:25 -0700 | [diff] [blame] | 175 | // Details of the current sink buffer. These become valid when a buffer is |
| 176 | // dequeued from the sink, and are used when queueing the buffer. |
| 177 | uint32_t mSinkBufferWidth, mSinkBufferHeight; |
| 178 | |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 179 | // |
| 180 | // Intra-frame state |
| 181 | // |
| 182 | |
| 183 | // Composition type and GLES buffer source for the current frame. |
| 184 | // Valid after prepareFrame(), cleared in onFrameCommitted. |
| 185 | CompositionType mCompositionType; |
| 186 | |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 187 | // mFbFence is the fence HWC should wait for before reading the framebuffer |
| 188 | // target buffer. |
| 189 | sp<Fence> mFbFence; |
| 190 | |
Jesse Hall | 028dc8f | 2013-08-20 16:35:32 -0700 | [diff] [blame] | 191 | // mOutputFence is the fence HWC should wait for before writing to the |
| 192 | // output buffer. |
| 193 | sp<Fence> mOutputFence; |
| 194 | |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 195 | // Producer slot numbers for the buffers to use for HWC framebuffer target |
| 196 | // and output. |
| 197 | int mFbProducerSlot; |
| 198 | int mOutputProducerSlot; |
| 199 | |
| 200 | // Debug only -- track the sequence of events in each frame so we can make |
| 201 | // sure they happen in the order we expect. This class implicitly models |
| 202 | // a state machine; this enum/variable makes it explicit. |
| 203 | // |
| 204 | // +-----------+-------------------+-------------+ |
| 205 | // | State | Event || Next State | |
| 206 | // +-----------+-------------------+-------------+ |
Jesse Hall | 028dc8f | 2013-08-20 16:35:32 -0700 | [diff] [blame] | 207 | // | IDLE | beginFrame || BEGUN | |
| 208 | // | BEGUN | prepareFrame || PREPARED | |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 209 | // | PREPARED | dequeueBuffer [1] || GLES | |
| 210 | // | PREPARED | advanceFrame [2] || HWC | |
| 211 | // | GLES | queueBuffer || GLES_DONE | |
| 212 | // | GLES_DONE | advanceFrame || HWC | |
| 213 | // | HWC | onFrameCommitted || IDLE | |
| 214 | // +-----------+-------------------++------------+ |
| 215 | // [1] COMPOSITION_GLES and COMPOSITION_MIXED frames. |
| 216 | // [2] COMPOSITION_HWC frames. |
| 217 | // |
| 218 | enum DbgState { |
| 219 | // no buffer dequeued, don't know anything about the next frame |
| 220 | DBG_STATE_IDLE, |
Jesse Hall | 028dc8f | 2013-08-20 16:35:32 -0700 | [diff] [blame] | 221 | // output buffer dequeued, framebuffer source not yet known |
| 222 | DBG_STATE_BEGUN, |
| 223 | // output buffer dequeued, framebuffer source known but not provided |
| 224 | // to GLES yet. |
Jesse Hall | 38efe86 | 2013-04-06 23:12:29 -0700 | [diff] [blame] | 225 | DBG_STATE_PREPARED, |
| 226 | // GLES driver has a buffer dequeued |
| 227 | DBG_STATE_GLES, |
| 228 | // GLES driver has queued the buffer, we haven't sent it to HWC yet |
| 229 | DBG_STATE_GLES_DONE, |
| 230 | // HWC has the buffer for this frame |
| 231 | DBG_STATE_HWC, |
| 232 | }; |
| 233 | DbgState mDbgState; |
| 234 | CompositionType mDbgLastCompositionType; |
| 235 | |
| 236 | const char* dbgStateStr() const; |
| 237 | static const char* dbgSourceStr(Source s); |
Dan Stoza | 7143316 | 2014-02-04 16:22:36 -0800 | [diff] [blame] | 238 | |
| 239 | bool mMustRecompose; |
Jesse Hall | 99c7dbb | 2013-03-14 14:29:29 -0700 | [diff] [blame] | 240 | }; |
| 241 | |
| 242 | // --------------------------------------------------------------------------- |
| 243 | } // namespace android |
| 244 | // --------------------------------------------------------------------------- |
| 245 | |
| 246 | #endif // ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H |
| 247 | |