• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // Stream.cpp: Implements the egl::Stream class, representing the stream
8 // where frames are streamed in. Implements EGLStreanKHR.
9 
10 #include "libANGLE/Stream.h"
11 
12 #include <EGL/eglext.h>
13 #include <platform/Platform.h>
14 
15 #include "common/debug.h"
16 #include "common/mathutil.h"
17 #include "common/platform.h"
18 #include "common/utilities.h"
19 #include "libANGLE/Context.h"
20 #include "libANGLE/Display.h"
21 #include "libANGLE/renderer/DisplayImpl.h"
22 #include "libANGLE/renderer/StreamProducerImpl.h"
23 
24 namespace egl
25 {
26 
Stream(Display * display,const AttributeMap & attribs)27 Stream::Stream(Display *display, const AttributeMap &attribs)
28     : mLabel(nullptr),
29       mDisplay(display),
30       mProducerImplementation(nullptr),
31       mState(EGL_STREAM_STATE_CREATED_KHR),
32       mProducerFrame(0),
33       mConsumerFrame(0),
34       mConsumerLatency(attribs.getAsInt(EGL_CONSUMER_LATENCY_USEC_KHR, 0)),
35       mConsumerAcquireTimeout(attribs.getAsInt(EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0)),
36       mPlaneCount(0),
37       mConsumerType(ConsumerType::NoConsumer),
38       mProducerType(ProducerType::NoProducer)
39 {
40     for (auto &plane : mPlanes)
41     {
42         plane.textureUnit = -1;
43         plane.texture     = nullptr;
44     }
45 }
46 
~Stream()47 Stream::~Stream()
48 {
49     SafeDelete(mProducerImplementation);
50     for (auto &plane : mPlanes)
51     {
52         if (plane.texture != nullptr)
53         {
54             plane.texture->releaseStream();
55         }
56     }
57 }
58 
setLabel(EGLLabelKHR label)59 void Stream::setLabel(EGLLabelKHR label)
60 {
61     mLabel = label;
62 }
63 
getLabel() const64 EGLLabelKHR Stream::getLabel() const
65 {
66     return mLabel;
67 }
68 
setConsumerLatency(EGLint latency)69 void Stream::setConsumerLatency(EGLint latency)
70 {
71     mConsumerLatency = latency;
72 }
73 
getConsumerLatency() const74 EGLint Stream::getConsumerLatency() const
75 {
76     return mConsumerLatency;
77 }
78 
getProducerFrame() const79 EGLuint64KHR Stream::getProducerFrame() const
80 {
81     return mProducerFrame;
82 }
83 
getConsumerFrame() const84 EGLuint64KHR Stream::getConsumerFrame() const
85 {
86     return mConsumerFrame;
87 }
88 
getState() const89 EGLenum Stream::getState() const
90 {
91     return mState;
92 }
93 
setConsumerAcquireTimeout(EGLint timeout)94 void Stream::setConsumerAcquireTimeout(EGLint timeout)
95 {
96     mConsumerAcquireTimeout = timeout;
97 }
98 
getConsumerAcquireTimeout() const99 EGLint Stream::getConsumerAcquireTimeout() const
100 {
101     return mConsumerAcquireTimeout;
102 }
103 
getProducerType() const104 Stream::ProducerType Stream::getProducerType() const
105 {
106     return mProducerType;
107 }
108 
getConsumerType() const109 Stream::ConsumerType Stream::getConsumerType() const
110 {
111     return mConsumerType;
112 }
113 
getPlaneCount() const114 EGLint Stream::getPlaneCount() const
115 {
116     return mPlaneCount;
117 }
118 
getImplementation()119 rx::StreamProducerImpl *Stream::getImplementation()
120 {
121     return mProducerImplementation;
122 }
123 
createConsumerGLTextureExternal(const AttributeMap & attributes,gl::Context * context)124 Error Stream::createConsumerGLTextureExternal(const AttributeMap &attributes, gl::Context *context)
125 {
126     ASSERT(mState == EGL_STREAM_STATE_CREATED_KHR);
127     ASSERT(mConsumerType == ConsumerType::NoConsumer);
128     ASSERT(mProducerType == ProducerType::NoProducer);
129     ASSERT(context != nullptr);
130 
131     const auto &glState = context->getState();
132     EGLenum bufferType  = attributes.getAsInt(EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
133     if (bufferType == EGL_RGB_BUFFER)
134     {
135         mPlanes[0].texture = glState.getTargetTexture(gl::TextureType::External);
136         ASSERT(mPlanes[0].texture != nullptr);
137         mPlanes[0].texture->bindStream(this);
138         mConsumerType = ConsumerType::GLTextureRGB;
139         mPlaneCount   = 1;
140     }
141     else
142     {
143         mPlaneCount = attributes.getAsInt(EGL_YUV_NUMBER_OF_PLANES_EXT, 2);
144         ASSERT(mPlaneCount <= 3);
145         for (EGLint i = 0; i < mPlaneCount; i++)
146         {
147             // Fetch all the textures
148             mPlanes[i].textureUnit = attributes.getAsInt(EGL_YUV_PLANE0_TEXTURE_UNIT_NV + i, -1);
149             if (mPlanes[i].textureUnit != EGL_NONE)
150             {
151                 mPlanes[i].texture =
152                     glState.getSamplerTexture(mPlanes[i].textureUnit, gl::TextureType::External);
153                 ASSERT(mPlanes[i].texture != nullptr);
154             }
155         }
156 
157         // Bind them to the stream
158         for (EGLint i = 0; i < mPlaneCount; i++)
159         {
160             if (mPlanes[i].textureUnit != EGL_NONE)
161             {
162                 mPlanes[i].texture->bindStream(this);
163             }
164         }
165         mConsumerType = ConsumerType::GLTextureYUV;
166     }
167 
168     mContext = context;
169     mState   = EGL_STREAM_STATE_CONNECTING_KHR;
170 
171     return NoError();
172 }
173 
createProducerD3D11Texture(const AttributeMap & attributes)174 Error Stream::createProducerD3D11Texture(const AttributeMap &attributes)
175 {
176     ASSERT(mState == EGL_STREAM_STATE_CONNECTING_KHR);
177     ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
178            mConsumerType == ConsumerType::GLTextureYUV);
179     ASSERT(mProducerType == ProducerType::NoProducer);
180 
181     mProducerImplementation =
182         mDisplay->getImplementation()->createStreamProducerD3DTexture(mConsumerType, attributes);
183     mProducerType = ProducerType::D3D11Texture;
184     mState        = EGL_STREAM_STATE_EMPTY_KHR;
185 
186     return NoError();
187 }
188 
189 // Called when the consumer of this stream starts using the stream
consumerAcquire(const gl::Context * context)190 Error Stream::consumerAcquire(const gl::Context *context)
191 {
192     ASSERT(mState == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR ||
193            mState == EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR);
194     ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
195            mConsumerType == ConsumerType::GLTextureYUV);
196     ASSERT(mProducerType == ProducerType::D3D11Texture);
197 
198     mState = EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR;
199     mConsumerFrame++;
200 
201     // Bind the planes to the gl textures
202     for (int i = 0; i < mPlaneCount; i++)
203     {
204         if (mPlanes[i].texture != nullptr)
205         {
206             ANGLE_TRY(ResultToEGL(mPlanes[i].texture->acquireImageFromStream(
207                 context, mProducerImplementation->getGLFrameDescription(i))));
208         }
209     }
210 
211     return NoError();
212 }
213 
consumerRelease(const gl::Context * context)214 Error Stream::consumerRelease(const gl::Context *context)
215 {
216     ASSERT(mState == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR ||
217            mState == EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR);
218     ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
219            mConsumerType == ConsumerType::GLTextureYUV);
220     ASSERT(mProducerType == ProducerType::D3D11Texture);
221 
222     // Release the images
223     for (int i = 0; i < mPlaneCount; i++)
224     {
225         if (mPlanes[i].texture != nullptr)
226         {
227             ANGLE_TRY(ResultToEGL(mPlanes[i].texture->releaseImageFromStream(context)));
228         }
229     }
230 
231     return NoError();
232 }
233 
isConsumerBoundToContext(const gl::Context * context) const234 bool Stream::isConsumerBoundToContext(const gl::Context *context) const
235 {
236     ASSERT(context != nullptr);
237     return (context == mContext);
238 }
239 
validateD3D11Texture(const void * texture,const AttributeMap & attributes) const240 Error Stream::validateD3D11Texture(const void *texture, const AttributeMap &attributes) const
241 {
242     ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
243            mConsumerType == ConsumerType::GLTextureYUV);
244     ASSERT(mProducerType == ProducerType::D3D11Texture);
245     ASSERT(mProducerImplementation != nullptr);
246 
247     return mProducerImplementation->validateD3DTexture(texture, attributes);
248 }
249 
postD3D11Texture(void * texture,const AttributeMap & attributes)250 Error Stream::postD3D11Texture(void *texture, const AttributeMap &attributes)
251 {
252     ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
253            mConsumerType == ConsumerType::GLTextureYUV);
254     ASSERT(mProducerType == ProducerType::D3D11Texture);
255 
256     mProducerImplementation->postD3DTexture(texture, attributes);
257     mProducerFrame++;
258 
259     mState = EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR;
260 
261     return NoError();
262 }
263 
264 // This is called when a texture object associated with this stream is destroyed. Even if multiple
265 // textures are bound, one being destroyed invalidates the stream, so all the remaining textures
266 // will be released and the stream will be invalidated.
releaseTextures()267 void Stream::releaseTextures()
268 {
269     for (auto &plane : mPlanes)
270     {
271         if (plane.texture != nullptr)
272         {
273             plane.texture->releaseStream();
274             plane.texture = nullptr;
275         }
276     }
277     mConsumerType = ConsumerType::NoConsumer;
278     mProducerType = ProducerType::NoProducer;
279     mState        = EGL_STREAM_STATE_DISCONNECTED_KHR;
280 }
281 
282 }  // namespace egl
283