diff options
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/Surface.cpp')
-rw-r--r-- | gfx/angle/checkout/src/libANGLE/Surface.cpp | 584 |
1 files changed, 584 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/Surface.cpp b/gfx/angle/checkout/src/libANGLE/Surface.cpp new file mode 100644 index 0000000000..e5a2cf110b --- /dev/null +++ b/gfx/angle/checkout/src/libANGLE/Surface.cpp @@ -0,0 +1,584 @@ +// +// 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 "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" +#include "libANGLE/trace.h" + +namespace egl +{ + +SurfaceState::SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn) + : label(nullptr), config(configIn), attributes(attributesIn), timestampsEnabled(false) +{} + +SurfaceState::~SurfaceState() = default; + +Surface::Surface(EGLint surfaceType, + const egl::Config *config, + const AttributeMap &attributes, + EGLenum buftype) + : FramebufferAttachmentObject(), + mState(config, attributes), + mImplementation(nullptr), + mRefCount(0), + mDestroyed(false), + mType(surfaceType), + mBuftype(buftype), + mPostSubBufferRequested(false), + mLargestPbuffer(false), + mGLColorspace(EGL_GL_COLORSPACE_LINEAR), + mVGAlphaFormat(EGL_VG_ALPHA_FORMAT_NONPRE), + mVGColorspace(EGL_VG_COLORSPACE_sRGB), + mMipmapTexture(false), + mMipmapLevel(0), + mHorizontalResolution(EGL_UNKNOWN), + mVerticalResolution(EGL_UNKNOWN), + mMultisampleResolve(EGL_MULTISAMPLE_RESOLVE_DEFAULT), + mFixedSize(false), + mFixedWidth(0), + mFixedHeight(0), + mTextureFormat(TextureFormat::NoTexture), + 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(nullptr), + mColorFormat(config->renderTargetFormat), + mDSFormat(config->depthStencilFormat), + mInitState(gl::InitState::Initialized) +{ + 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); + + if (mType == EGL_PBUFFER_BIT) + { + mLargestPbuffer = (attributes.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE); + } + + mGLColorspace = + static_cast<EGLenum>(attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR)); + mVGAlphaFormat = + static_cast<EGLenum>(attributes.get(EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_NONPRE)); + mVGColorspace = static_cast<EGLenum>(attributes.get(EGL_VG_COLORSPACE, EGL_VG_COLORSPACE_sRGB)); + mMipmapTexture = (attributes.get(EGL_MIPMAP_TEXTURE, EGL_FALSE) == EGL_TRUE); + + mDirectComposition = (attributes.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE); + + mRobustResourceInitialization = + (attributes.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE); + if (mRobustResourceInitialization) + { + mInitState = gl::InitState::MayNeedInit; + } + + 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 = attributes.getAsPackedEnum(EGL_TEXTURE_FORMAT, TextureFormat::NoTexture); + 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() {} + +rx::FramebufferAttachmentObjectImpl *Surface::getAttachmentImpl() const +{ + return mImplementation; +} + +Error Surface::destroyImpl(const Display *display) +{ + if (mImplementation) + { + mImplementation->destroy(display); + } + + ASSERT(!mTexture); + + SafeDelete(mImplementation); + + delete this; + return NoError(); +} + +void Surface::postSwap(const Display *display) +{ + if (mRobustResourceInitialization && mSwapBehavior != EGL_BUFFER_PRESERVED) + { + mInitState = gl::InitState::MayNeedInit; + onStateChange(angle::SubjectMessage::SubjectChanged); + } + + display->onPostSwap(); +} + +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(); + + if (mBuftype == EGL_IOSURFACE_ANGLE) + { + GLenum internalFormat = + static_cast<GLenum>(mState.attributes.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE)); + GLenum type = static_cast<GLenum>(mState.attributes.get(EGL_TEXTURE_TYPE_ANGLE)); + mColorFormat = gl::Format(internalFormat, type); + } + if (mBuftype == EGL_D3D_TEXTURE_ANGLE) + { + const angle::Format *colorFormat = mImplementation->getD3DTextureColorFormat(); + ASSERT(colorFormat != nullptr); + GLenum internalFormat = colorFormat->fboImplementationInternalFormat; + mColorFormat = gl::Format(internalFormat, colorFormat->componentType); + mGLColorspace = EGL_GL_COLORSPACE_LINEAR; + if (mColorFormat.info->colorEncoding == GL_SRGB) + { + mGLColorspace = EGL_GL_COLORSPACE_SRGB; + } + } + + if (mType == EGL_WINDOW_BIT && display->getExtensions().getFrameTimestamps) + { + mState.supportedCompositorTimings = mImplementation->getSupportedCompositorTimings(); + mState.supportedTimestamps = mImplementation->getSupportedTimestamps(); + } + + return NoError(); +} + +Error Surface::makeCurrent(const gl::Context *context) +{ + ANGLE_TRY(mImplementation->makeCurrent(context)); + + mRefCount++; + return NoError(); +} + +Error Surface::unMakeCurrent(const gl::Context *context) +{ + ANGLE_TRY(mImplementation->unMakeCurrent(context)); + return releaseRef(context->getDisplay()); +} + +Error Surface::releaseRef(const Display *display) +{ + ASSERT(mRefCount > 0); + mRefCount--; + if (mRefCount == 0 && mDestroyed) + { + ASSERT(display); + return destroyImpl(display); + } + + return NoError(); +} + +Error Surface::onDestroy(const Display *display) +{ + mDestroyed = true; + if (mRefCount == 0) + { + return destroyImpl(display); + } + return NoError(); +} + +void Surface::setLabel(EGLLabelKHR label) +{ + mState.label = label; +} + +EGLLabelKHR Surface::getLabel() const +{ + return mState.label; +} + +EGLint Surface::getType() const +{ + return mType; +} + +Error Surface::swap(const gl::Context *context) +{ + ANGLE_TRACE_EVENT0("gpu.angle", "egl::Surface::swap"); + + ANGLE_TRY(mImplementation->swap(context)); + postSwap(context->getDisplay()); + return NoError(); +} + +Error Surface::swapWithDamage(const gl::Context *context, EGLint *rects, EGLint n_rects) +{ + ANGLE_TRY(mImplementation->swapWithDamage(context, rects, n_rects)); + postSwap(context->getDisplay()); + return NoError(); +} + +Error Surface::postSubBuffer(const gl::Context *context, + EGLint x, + EGLint y, + EGLint width, + EGLint height) +{ + if (width == 0 || height == 0) + { + return egl::NoError(); + } + + return mImplementation->postSubBuffer(context, x, y, width, height); +} + +Error Surface::setPresentationTime(EGLnsecsANDROID time) +{ + return mImplementation->setPresentationTime(time); +} + +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); +} + +void Surface::setMipmapLevel(EGLint level) +{ + // Level is set but ignored + UNIMPLEMENTED(); + mMipmapLevel = level; +} + +void Surface::setMultisampleResolve(EGLenum resolve) +{ + // Behaviour is set but ignored + UNIMPLEMENTED(); + mMultisampleResolve = resolve; +} + +void Surface::setSwapBehavior(EGLenum behavior) +{ + // Behaviour is set but ignored + UNIMPLEMENTED(); + mSwapBehavior = behavior; +} + +void Surface::setFixedWidth(EGLint width) +{ + mFixedWidth = width; + mImplementation->setFixedWidth(width); +} + +void Surface::setFixedHeight(EGLint height) +{ + mFixedHeight = height; + mImplementation->setFixedHeight(height); +} + +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; +} + +TextureFormat Surface::getTextureFormat() const +{ + return mTextureFormat; +} + +EGLenum Surface::getTextureTarget() const +{ + return mTextureTarget; +} + +bool Surface::getLargestPbuffer() const +{ + return mLargestPbuffer; +} + +EGLenum Surface::getGLColorspace() const +{ + return mGLColorspace; +} + +EGLenum Surface::getVGAlphaFormat() const +{ + return mVGAlphaFormat; +} + +EGLenum Surface::getVGColorspace() const +{ + return mVGColorspace; +} + +bool Surface::getMipmapTexture() const +{ + return mMipmapTexture; +} + +EGLint Surface::getMipmapLevel() const +{ + return mMipmapLevel; +} + +EGLint Surface::getHorizontalResolution() const +{ + return mHorizontalResolution; +} + +EGLint Surface::getVerticalResolution() const +{ + return mVerticalResolution; +} + +EGLenum Surface::getMultisampleResolve() const +{ + return mMultisampleResolve; +} + +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(gl::Context *context, gl::Texture *texture, EGLint buffer) +{ + ASSERT(!mTexture); + ANGLE_TRY(mImplementation->bindTexImage(context, texture, buffer)); + + if (texture->bindTexImageFromSurface(context, this) == angle::Result::Stop) + { + return Error(EGL_BAD_SURFACE); + } + mTexture = texture; + mRefCount++; + + return NoError(); +} + +Error Surface::releaseTexImage(const gl::Context *context, EGLint buffer) +{ + ASSERT(context); + + ANGLE_TRY(mImplementation->releaseTexImage(context, buffer)); + + ASSERT(mTexture); + ANGLE_TRY(ResultToEGL(mTexture->releaseTexImageFromSurface(context))); + + return releaseTexImageFromTexture(context); +} + +Error Surface::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) +{ + return mImplementation->getSyncValues(ust, msc, sbc); +} + +Error Surface::releaseTexImageFromTexture(const gl::Context *context) +{ + ASSERT(mTexture); + mTexture = nullptr; + return releaseRef(context->getDisplay()); +} + +gl::Extents Surface::getAttachmentSize(const gl::ImageIndex & /*target*/) const +{ + return gl::Extents(getWidth(), getHeight(), 1); +} + +gl::Format Surface::getAttachmentFormat(GLenum binding, const gl::ImageIndex &target) const +{ + return (binding == GL_BACK ? mColorFormat : mDSFormat); +} + +GLsizei Surface::getAttachmentSamples(const gl::ImageIndex &target) const +{ + return getConfig()->samples; +} + +bool Surface::isRenderable(const gl::Context *context, + GLenum binding, + const gl::ImageIndex &imageIndex) const +{ + return true; +} + +GLuint Surface::getId() const +{ + UNREACHABLE(); + return 0; +} + +gl::Framebuffer *Surface::createDefaultFramebuffer(const gl::Context *context) +{ + return new gl::Framebuffer(context, this); +} + +gl::InitState Surface::initState(const gl::ImageIndex & /*imageIndex*/) const +{ + return mInitState; +} + +void Surface::setInitState(const gl::ImageIndex & /*imageIndex*/, gl::InitState initState) +{ + mInitState = initState; +} + +void Surface::setTimestampsEnabled(bool enabled) +{ + mImplementation->setTimestampsEnabled(enabled); + mState.timestampsEnabled = enabled; +} + +bool Surface::isTimestampsEnabled() const +{ + return mState.timestampsEnabled; +} + +const SupportedCompositorTiming &Surface::getSupportedCompositorTimings() const +{ + return mState.supportedCompositorTimings; +} + +Error Surface::getCompositorTiming(EGLint numTimestamps, + const EGLint *names, + EGLnsecsANDROID *values) const +{ + return mImplementation->getCompositorTiming(numTimestamps, names, values); +} + +Error Surface::getNextFrameId(EGLuint64KHR *frameId) const +{ + return mImplementation->getNextFrameId(frameId); +} + +const SupportedTimestamps &Surface::getSupportedTimestamps() const +{ + return mState.supportedTimestamps; +} + +Error Surface::getFrameTimestamps(EGLuint64KHR frameId, + EGLint numTimestamps, + const EGLint *timestamps, + EGLnsecsANDROID *values) const +{ + return mImplementation->getFrameTimestamps(frameId, numTimestamps, timestamps, values); +} + +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, buftype) +{ + 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() {} + +// SurfaceDeleter implementation. + +SurfaceDeleter::SurfaceDeleter(const Display *display) : mDisplay(display) {} + +SurfaceDeleter::~SurfaceDeleter() {} + +void SurfaceDeleter::operator()(Surface *surface) +{ + ANGLE_SWALLOW_ERR(surface->onDestroy(mDisplay)); +} + +} // namespace egl |