Edit

kc3-lang/angle/src/libANGLE/Stream.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2016-06-09 07:07:18
    Hash : dfde6abf
    Message : Context: Remove mutable gl::State getter. This will preserve layering - the API layer doesn't mutate the state directly, it passes the API call through to the Context. Is also removes the possiblity of any shenanigans of the Validation layer changing the GL state. Also, this CL refactors a few validation entry points to take ValidationContext instead of Context. ValidationContext will be the correct way to interact with the gl::Context in the Validation code. Finally, additional refactorings make ContextState a proper class with private data. This allows the ContextState itself to keep a mutable pointer to the gl::State, so ValidationContext can modify it if necessary (and it will be necessary for Framebuffer completeness caching). BUG=angleproject:1388 Change-Id: I86ab3561573caa9535c8d1b8aad4ab3d0e7cd470 Reviewed-on: https://chromium-review.googlesource.com/348954 Reviewed-by: Geoff Lang <geofflang@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>

  • src/libANGLE/Stream.cpp
  • //
    // Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    // Stream.cpp: Implements the egl::Stream class, representing the stream
    // where frames are streamed in. Implements EGLStreanKHR.
    
    #include "libANGLE/Stream.h"
    
    #include <platform/Platform.h>
    #include <EGL/eglext.h>
    
    #include "common/debug.h"
    #include "common/mathutil.h"
    #include "common/platform.h"
    #include "common/utilities.h"
    #include "libANGLE/Context.h"
    #include "libANGLE/Display.h"
    #include "libANGLE/renderer/DisplayImpl.h"
    #include "libANGLE/renderer/StreamProducerImpl.h"
    
    namespace egl
    {
    
    Stream::Stream(Display *display, const AttributeMap &attribs)
        : mDisplay(display),
          mProducerImplementation(nullptr),
          mState(EGL_STREAM_STATE_CREATED_KHR),
          mProducerFrame(0),
          mConsumerFrame(0),
          mConsumerLatency(attribs.getAsInt(EGL_CONSUMER_LATENCY_USEC_KHR, 0)),
          mConsumerAcquireTimeout(attribs.getAsInt(EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0)),
          mPlaneCount(0),
          mConsumerType(ConsumerType::NoConsumer),
          mProducerType(ProducerType::NoProducer)
    {
        for (auto &plane : mPlanes)
        {
            plane.textureUnit = -1;
            plane.texture     = nullptr;
        }
    }
    
    Stream::~Stream()
    {
        SafeDelete(mProducerImplementation);
        for (auto &plane : mPlanes)
        {
            if (plane.texture != nullptr)
            {
                plane.texture->releaseStream();
            }
        }
    }
    
    void Stream::setConsumerLatency(EGLint latency)
    {
        mConsumerLatency = latency;
    }
    
    EGLint Stream::getConsumerLatency() const
    {
        return mConsumerLatency;
    }
    
    EGLuint64KHR Stream::getProducerFrame() const
    {
        return mProducerFrame;
    }
    
    EGLuint64KHR Stream::getConsumerFrame() const
    {
        return mConsumerFrame;
    }
    
    EGLenum Stream::getState() const
    {
        return mState;
    }
    
    void Stream::setConsumerAcquireTimeout(EGLint timeout)
    {
        mConsumerAcquireTimeout = timeout;
    }
    
    EGLint Stream::getConsumerAcquireTimeout() const
    {
        return mConsumerAcquireTimeout;
    }
    
    Stream::ProducerType Stream::getProducerType() const
    {
        return mProducerType;
    }
    
    Stream::ConsumerType Stream::getConsumerType() const
    {
        return mConsumerType;
    }
    
    EGLint Stream::getPlaneCount() const
    {
        return mPlaneCount;
    }
    
    rx::StreamProducerImpl *Stream::getImplementation()
    {
        return mProducerImplementation;
    }
    
    Error Stream::createConsumerGLTextureExternal(const AttributeMap &attributes, gl::Context *context)
    {
        ASSERT(mState == EGL_STREAM_STATE_CREATED_KHR);
        ASSERT(mConsumerType == ConsumerType::NoConsumer);
        ASSERT(mProducerType == ProducerType::NoProducer);
        ASSERT(context != nullptr);
    
        const auto &glState = context->getGLState();
        EGLenum bufferType = attributes.getAsInt(EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
        if (bufferType == EGL_RGB_BUFFER)
        {
            mPlanes[0].texture = glState.getTargetTexture(GL_TEXTURE_EXTERNAL_OES);
            ASSERT(mPlanes[0].texture != nullptr);
            mPlanes[0].texture->bindStream(this);
            mConsumerType = ConsumerType::GLTextureRGB;
            mPlaneCount   = 1;
        }
        else
        {
            mPlaneCount = attributes.getAsInt(EGL_YUV_NUMBER_OF_PLANES_EXT, 2);
            ASSERT(mPlaneCount <= 3);
            for (EGLint i = 0; i < mPlaneCount; i++)
            {
                // Fetch all the textures
                mPlanes[i].textureUnit = attributes.getAsInt(EGL_YUV_PLANE0_TEXTURE_UNIT_NV + i, -1);
                if (mPlanes[i].textureUnit != EGL_NONE)
                {
                    mPlanes[i].texture =
                        glState.getSamplerTexture(mPlanes[i].textureUnit, GL_TEXTURE_EXTERNAL_OES);
                    ASSERT(mPlanes[i].texture != nullptr);
                }
            }
    
            // Bind them to the stream
            for (EGLint i = 0; i < mPlaneCount; i++)
            {
                if (mPlanes[i].textureUnit != EGL_NONE)
                {
                    mPlanes[i].texture->bindStream(this);
                }
            }
            mConsumerType = ConsumerType::GLTextureYUV;
        }
    
        mContext = context;
        mState   = EGL_STREAM_STATE_CONNECTING_KHR;
    
        return Error(EGL_SUCCESS);
    }
    
    Error Stream::createProducerD3D11TextureNV12(const AttributeMap &attributes)
    {
        ASSERT(mState == EGL_STREAM_STATE_CONNECTING_KHR);
        ASSERT(mConsumerType == ConsumerType::GLTextureYUV);
        ASSERT(mProducerType == ProducerType::NoProducer);
        ASSERT(mPlaneCount == 2);
    
        mProducerImplementation = mDisplay->getImplementation()->createStreamProducerD3DTextureNV12(
            mConsumerType, attributes);
        mProducerType = ProducerType::D3D11TextureNV12;
        mState        = EGL_STREAM_STATE_EMPTY_KHR;
    
        return Error(EGL_SUCCESS);
    }
    
    // Called when the consumer of this stream starts using the stream
    Error Stream::consumerAcquire()
    {
        ASSERT(mState == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR ||
               mState == EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR);
        ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
               mConsumerType == ConsumerType::GLTextureYUV);
        ASSERT(mProducerType == ProducerType::D3D11TextureNV12);
    
        mState = EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR;
        mConsumerFrame++;
    
        // Bind the planes to the gl textures
        for (int i = 0; i < mPlaneCount; i++)
        {
            if (mPlanes[i].texture != nullptr)
            {
                mPlanes[i].texture->acquireImageFromStream(
                    mProducerImplementation->getGLFrameDescription(i));
            }
        }
    
        return Error(EGL_SUCCESS);
    }
    
    Error Stream::consumerRelease()
    {
        ASSERT(mState == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR ||
               mState == EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR);
        ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
               mConsumerType == ConsumerType::GLTextureYUV);
        ASSERT(mProducerType == ProducerType::D3D11TextureNV12);
    
        // Release the images
        for (int i = 0; i < mPlaneCount; i++)
        {
            if (mPlanes[i].texture != nullptr)
            {
                mPlanes[i].texture->releaseImageFromStream();
            }
        }
    
        return Error(EGL_SUCCESS);
    }
    
    bool Stream::isConsumerBoundToContext(const gl::Context *context) const
    {
        ASSERT(context != nullptr);
        return (context == mContext);
    }
    
    Error Stream::validateD3D11NV12Texture(void *texture) const
    {
        ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
               mConsumerType == ConsumerType::GLTextureYUV);
        ASSERT(mProducerType == ProducerType::D3D11TextureNV12);
        ASSERT(mProducerImplementation != nullptr);
    
        return mProducerImplementation->validateD3DNV12Texture(texture);
    }
    
    Error Stream::postD3D11NV12Texture(void *texture, const AttributeMap &attributes)
    {
        ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
               mConsumerType == ConsumerType::GLTextureYUV);
        ASSERT(mProducerType == ProducerType::D3D11TextureNV12);
    
        mProducerImplementation->postD3DNV12Texture(texture, attributes);
        mProducerFrame++;
    
        mState = EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR;
    
        return Error(EGL_SUCCESS);
    }
    
    // This is called when a texture object associated with this stream is destroyed. Even if multiple
    // textures are bound, one being destroyed invalidates the stream, so all the remaining textures
    // will be released and the stream will be invalidated.
    void Stream::releaseTextures()
    {
        for (auto &plane : mPlanes)
        {
            if (plane.texture != nullptr)
            {
                plane.texture->releaseStream();
                plane.texture = nullptr;
            }
        }
        mConsumerType = ConsumerType::NoConsumer;
        mProducerType = ProducerType::NoProducer;
        mState        = EGL_STREAM_STATE_DISCONNECTED_KHR;
    }
    
    }  // namespace egl