tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Stream.cpp (7909B)


      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/PlatformMethods.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 
     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 
     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 
     59 void Stream::setLabel(EGLLabelKHR label)
     60 {
     61    mLabel = label;
     62 }
     63 
     64 EGLLabelKHR Stream::getLabel() const
     65 {
     66    return mLabel;
     67 }
     68 
     69 void Stream::setConsumerLatency(EGLint latency)
     70 {
     71    mConsumerLatency = latency;
     72 }
     73 
     74 EGLint Stream::getConsumerLatency() const
     75 {
     76    return mConsumerLatency;
     77 }
     78 
     79 EGLuint64KHR Stream::getProducerFrame() const
     80 {
     81    return mProducerFrame;
     82 }
     83 
     84 EGLuint64KHR Stream::getConsumerFrame() const
     85 {
     86    return mConsumerFrame;
     87 }
     88 
     89 EGLenum Stream::getState() const
     90 {
     91    return mState;
     92 }
     93 
     94 void Stream::setConsumerAcquireTimeout(EGLint timeout)
     95 {
     96    mConsumerAcquireTimeout = timeout;
     97 }
     98 
     99 EGLint Stream::getConsumerAcquireTimeout() const
    100 {
    101    return mConsumerAcquireTimeout;
    102 }
    103 
    104 Stream::ProducerType Stream::getProducerType() const
    105 {
    106    return mProducerType;
    107 }
    108 
    109 Stream::ConsumerType Stream::getConsumerType() const
    110 {
    111    return mConsumerType;
    112 }
    113 
    114 EGLint Stream::getPlaneCount() const
    115 {
    116    return mPlaneCount;
    117 }
    118 
    119 rx::StreamProducerImpl *Stream::getImplementation()
    120 {
    121    return mProducerImplementation;
    122 }
    123 
    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 
    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
    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 
    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 
    234 bool Stream::isConsumerBoundToContext(const gl::Context *context) const
    235 {
    236    ASSERT(context != nullptr);
    237    return (context == mContext);
    238 }
    239 
    240 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 
    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.
    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