Edit

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

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2017-06-20 12:57:39
    Hash : 4928b7ca
    Message : Proliferate gl::Context everywhere. This gives the D3D back-end access to the GL state almost anywhere. This uses the onDestroy hook for Textures to push errors up from destructors, although they still don't quite make it to the Context. There are places, such as in EGL object (Context/Surface) destruction, where we end up calling through to GL implementation internals without having access to a gl::Context. We handle this via a proxy Context to a Display, basically a null context, that has access to impl-side state like the Renderer pointer if necessary. It does not have access to the normal GL state. Also Pass gl::Context to RefCountObject::release(). Since we're using destroy() methods now, we should not ever call the destructor directly. BUG=angleproject:1156 Change-Id: Ie4c32ad6bf6caaff0289901f30b5c6bafa2ce259 Reviewed-on: https://chromium-review.googlesource.com/529707 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org>

  • src/libANGLE/Surface.cpp
  • //
    // Copyright (c) 2002-2014 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.
    //
    
    // Surface.cpp: Implements the egl::Surface class, representing a drawing surface
    // such as the client area of a window, including any back buffers.
    // Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
    
    #include "libANGLE/Surface.h"
    
    #include <EGL/eglext.h>
    
    #include <iostream>
    
    #include "libANGLE/Config.h"
    #include "libANGLE/Context.h"
    #include "libANGLE/Display.h"
    #include "libANGLE/Framebuffer.h"
    #include "libANGLE/Texture.h"
    #include "libANGLE/Thread.h"
    #include "libANGLE/formatutils.h"
    #include "libANGLE/renderer/EGLImplFactory.h"
    
    namespace egl
    {
    
    SurfaceState::SurfaceState(const egl::Config *configIn)
        : defaultFramebuffer(nullptr), config(configIn)
    {
    }
    
    Surface::Surface(EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes)
        : FramebufferAttachmentObject(),
          mState(config),
          mImplementation(nullptr),
          mCurrentCount(0),
          mDestroyed(false),
          mType(surfaceType),
          mPostSubBufferRequested(false),
          mFixedSize(false),
          mFixedWidth(0),
          mFixedHeight(0),
          mTextureFormat(EGL_NO_TEXTURE),
          mTextureTarget(EGL_NO_TEXTURE),
          // FIXME: Determine actual pixel aspect ratio
          mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)),
          mRenderBuffer(EGL_BACK_BUFFER),
          mSwapBehavior(EGL_NONE),
          mOrientation(0),
          mTexture(),
          mBackFormat(config->renderTargetFormat),
          mDSFormat(config->depthStencilFormat)
    {
        mPostSubBufferRequested = (attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE);
        mFlexibleSurfaceCompatibilityRequested =
            (attributes.get(EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_FALSE) == EGL_TRUE);
    
        mDirectComposition = (attributes.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE);
    
        mFixedSize = (attributes.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE);
        if (mFixedSize)
        {
            mFixedWidth  = static_cast<size_t>(attributes.get(EGL_WIDTH, 0));
            mFixedHeight = static_cast<size_t>(attributes.get(EGL_HEIGHT, 0));
        }
    
        if (mType != EGL_WINDOW_BIT)
        {
            mTextureFormat = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE));
            mTextureTarget = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE));
        }
    
        mOrientation = static_cast<EGLint>(attributes.get(EGL_SURFACE_ORIENTATION_ANGLE, 0));
    }
    
    Surface::~Surface()
    {
    }
    
    Error Surface::destroyImpl(const Display *display)
    {
        if (mState.defaultFramebuffer)
        {
            mState.defaultFramebuffer->destroyDefault(display);
        }
        if (mImplementation)
        {
            mImplementation->destroy(display);
        }
    
        if (mTexture.get())
        {
            if (mImplementation)
            {
                ANGLE_TRY(mImplementation->releaseTexImage(EGL_BACK_BUFFER));
            }
            auto glErr = mTexture->releaseTexImageFromSurface(display->getProxyContext());
            if (glErr.isError())
            {
                return Error(EGL_BAD_SURFACE);
            }
            mTexture.set(nullptr, nullptr);
        }
    
        if (mState.defaultFramebuffer)
        {
            mState.defaultFramebuffer->onDestroy(display->getProxyContext());
        }
        SafeDelete(mState.defaultFramebuffer);
        SafeDelete(mImplementation);
    
        delete this;
        return NoError();
    }
    
    Error Surface::initialize(const Display *display)
    {
        ANGLE_TRY(mImplementation->initialize(display));
    
        // Initialized here since impl is nullptr in the constructor.
        // Must happen after implementation initialize for Android.
        mSwapBehavior = mImplementation->getSwapBehavior();
    
        // Must happen after implementation initialize for OSX.
        mState.defaultFramebuffer = createDefaultFramebuffer(display);
        ASSERT(mState.defaultFramebuffer != nullptr);
    
        return NoError();
    }
    
    Error Surface::setIsCurrent(const gl::Context *context, bool isCurrent)
    {
        if (isCurrent)
        {
            mCurrentCount++;
            return NoError();
        }
    
        ASSERT(mCurrentCount > 0);
        mCurrentCount--;
        if (mCurrentCount == 0 && mDestroyed)
        {
            ASSERT(context);
            return destroyImpl(context->getCurrentDisplay());
        }
        return NoError();
    }
    
    Error Surface::onDestroy(const Display *display)
    {
        mDestroyed = true;
        if (mCurrentCount == 0)
        {
            return destroyImpl(display);
        }
        return NoError();
    }
    
    EGLint Surface::getType() const
    {
        return mType;
    }
    
    Error Surface::swap(const gl::Context *context)
    {
        return mImplementation->swap(context);
    }
    
    Error Surface::swapWithDamage(const gl::Context *context, EGLint *rects, EGLint n_rects)
    {
        return mImplementation->swapWithDamage(context, rects, n_rects);
    }
    
    Error Surface::postSubBuffer(const gl::Context *context,
                                 EGLint x,
                                 EGLint y,
                                 EGLint width,
                                 EGLint height)
    {
        return mImplementation->postSubBuffer(context, x, y, width, height);
    }
    
    Error Surface::querySurfacePointerANGLE(EGLint attribute, void **value)
    {
        return mImplementation->querySurfacePointerANGLE(attribute, value);
    }
    
    EGLint Surface::isPostSubBufferSupported() const
    {
        return mPostSubBufferRequested && mImplementation->isPostSubBufferSupported();
    }
    
    void Surface::setSwapInterval(EGLint interval)
    {
        mImplementation->setSwapInterval(interval);
    }
    
    const Config *Surface::getConfig() const
    {
        return mState.config;
    }
    
    EGLint Surface::getPixelAspectRatio() const
    {
        return mPixelAspectRatio;
    }
    
    EGLenum Surface::getRenderBuffer() const
    {
        return mRenderBuffer;
    }
    
    EGLenum Surface::getSwapBehavior() const
    {
        return mSwapBehavior;
    }
    
    EGLenum Surface::getTextureFormat() const
    {
        return mTextureFormat;
    }
    
    EGLenum Surface::getTextureTarget() const
    {
        return mTextureTarget;
    }
    
    EGLint Surface::isFixedSize() const
    {
        return mFixedSize;
    }
    
    EGLint Surface::getWidth() const
    {
        return mFixedSize ? static_cast<EGLint>(mFixedWidth) : mImplementation->getWidth();
    }
    
    EGLint Surface::getHeight() const
    {
        return mFixedSize ? static_cast<EGLint>(mFixedHeight) : mImplementation->getHeight();
    }
    
    Error Surface::bindTexImage(const gl::Context *context, gl::Texture *texture, EGLint buffer)
    {
        ASSERT(!mTexture.get());
        ANGLE_TRY(mImplementation->bindTexImage(texture, buffer));
    
        auto glErr = texture->bindTexImageFromSurface(context, this);
        if (glErr.isError())
        {
            return Error(EGL_BAD_SURFACE);
        }
        mTexture.set(context, texture);
    
        return NoError();
    }
    
    Error Surface::releaseTexImage(const gl::Context *context, EGLint buffer)
    {
        ASSERT(context);
    
        ANGLE_TRY(mImplementation->releaseTexImage(buffer));
    
        ASSERT(mTexture.get());
        auto glErr = mTexture->releaseTexImageFromSurface(context);
        if (glErr.isError())
        {
            return Error(EGL_BAD_SURFACE);
        }
        mTexture.set(context, nullptr);
    
        return NoError();
    }
    
    Error Surface::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
    {
        return mImplementation->getSyncValues(ust, msc, sbc);
    }
    
    void Surface::releaseTexImageFromTexture(const gl::Context *context)
    {
        ASSERT(mTexture.get());
        mTexture.set(context, nullptr);
    }
    
    gl::Extents Surface::getAttachmentSize(const gl::ImageIndex & /*target*/) const
    {
        return gl::Extents(getWidth(), getHeight(), 1);
    }
    
    const gl::Format &Surface::getAttachmentFormat(GLenum binding, const gl::ImageIndex &target) const
    {
        return (binding == GL_BACK ? mBackFormat : mDSFormat);
    }
    
    GLsizei Surface::getAttachmentSamples(const gl::ImageIndex &target) const
    {
        return getConfig()->samples;
    }
    
    GLuint Surface::getId() const
    {
        UNREACHABLE();
        return 0;
    }
    
    gl::Framebuffer *Surface::createDefaultFramebuffer(const Display *display)
    {
        return new gl::Framebuffer(display, this);
    }
    
    WindowSurface::WindowSurface(rx::EGLImplFactory *implFactory,
                                 const egl::Config *config,
                                 EGLNativeWindowType window,
                                 const AttributeMap &attribs)
        : Surface(EGL_WINDOW_BIT, config, attribs)
    {
        mImplementation = implFactory->createWindowSurface(mState, window, attribs);
    }
    
    WindowSurface::~WindowSurface()
    {
    }
    
    PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
                                   const Config *config,
                                   const AttributeMap &attribs)
        : Surface(EGL_PBUFFER_BIT, config, attribs)
    {
        mImplementation = implFactory->createPbufferSurface(mState, attribs);
    }
    
    PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
                                   const Config *config,
                                   EGLenum buftype,
                                   EGLClientBuffer clientBuffer,
                                   const AttributeMap &attribs)
        : Surface(EGL_PBUFFER_BIT, config, attribs)
    {
        mImplementation =
            implFactory->createPbufferFromClientBuffer(mState, buftype, clientBuffer, attribs);
    }
    
    PbufferSurface::~PbufferSurface()
    {
    }
    
    PixmapSurface::PixmapSurface(rx::EGLImplFactory *implFactory,
                                 const Config *config,
                                 NativePixmapType nativePixmap,
                                 const AttributeMap &attribs)
        : Surface(EGL_PIXMAP_BIT, config, attribs)
    {
        mImplementation = implFactory->createPixmapSurface(mState, nativePixmap, attribs);
    }
    
    PixmapSurface::~PixmapSurface()
    {
    }
    
    }  // namespace egl