//
// Copyright 2002 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/formatutils.h"
#include "libANGLE/renderer/EGLImplFactory.h"
#include "libANGLE/trace.h"

namespace egl
{
namespace
{
angle::SubjectIndex kSurfaceImplSubjectIndex = 0;
}  // namespace

SurfaceState::SurfaceState(SurfaceID idIn,
                           const egl::Config *configIn,
                           const AttributeMap &attributesIn)
    : id(idIn),
      label(nullptr),
      config((configIn != nullptr) ? new egl::Config(*configIn) : nullptr),
      attributes(attributesIn),
      timestampsEnabled(false),
      autoRefreshEnabled(false),
      directComposition(false),
      swapBehavior(EGL_NONE),
      swapInterval(0)
{
    directComposition = attributes.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE;
    swapInterval      = attributes.getAsInt(EGL_SWAP_INTERVAL_ANGLE, 1);
}

SurfaceState::~SurfaceState()
{
    delete config;
}

bool SurfaceState::isRobustResourceInitEnabled() const
{
    return attributes.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE;
}

bool SurfaceState::hasProtectedContent() const
{
    return attributes.get(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) == EGL_TRUE;
}

Surface::Surface(EGLint surfaceType,
                 SurfaceID id,
                 const egl::Config *config,
                 const AttributeMap &attributes,
                 bool forceRobustResourceInit,
                 EGLenum buftype)
    : FramebufferAttachmentObject(),
      mState(id, 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),
      mRequestedRenderBuffer(EGL_BACK_BUFFER),
      mRequestedSwapInterval(mState.swapInterval),
      mOrientation(0),
      mTexture(nullptr),
      mColorFormat(config->renderTargetFormat),
      mDSFormat(config->depthStencilFormat),
      mIsCurrentOnAnyContext(false),
      mLockBufferPtr(nullptr),
      mLockBufferPitch(0),
      mBufferAgeQueriedSinceLastSwap(false),
      mIsDamageRegionSet(false),
      mColorInitState(gl::InitState::Initialized),
      mDepthStencilInitState(gl::InitState::Initialized),
      mImplObserverBinding(this, kSurfaceImplSubjectIndex)
{
    mPostSubBufferRequested =
        (attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE);

    if (mType == EGL_PBUFFER_BIT)
    {
        mLargestPbuffer = (attributes.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE);
    }

    if (mType == EGL_PIXMAP_BIT)
    {
        mRenderBuffer          = EGL_SINGLE_BUFFER;
        mRequestedRenderBuffer = EGL_SINGLE_BUFFER;
    }

    if (mType == EGL_WINDOW_BIT)
    {
        mRenderBuffer          = mState.attributes.getAsInt(EGL_RENDER_BUFFER, EGL_BACK_BUFFER);
        mRequestedRenderBuffer = mRenderBuffer;
    }

    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);

    mRobustResourceInitialization =
        forceRobustResourceInit ||
        (attributes.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE);
    if (mRobustResourceInitialization)
    {
        mColorInitState        = gl::InitState::MayNeedInit;
        mDepthStencilInitState = 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));

    mTextureOffset.x = static_cast<int>(mState.attributes.get(EGL_TEXTURE_OFFSET_X_ANGLE, 0));
    mTextureOffset.y = static_cast<int>(mState.attributes.get(EGL_TEXTURE_OFFSET_Y_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 gl::Context *context, const rx::SurfaceSwapFeedback &feedback)
{
    if (feedback.swapChainImageChanged)
    {
        context->onSwapChainImageChanged();
    }

    if (mRobustResourceInitialization && mState.swapBehavior != EGL_BUFFER_PRESERVED)
    {
        mColorInitState        = gl::InitState::MayNeedInit;
        mDepthStencilInitState = gl::InitState::MayNeedInit;
        onStateChange(angle::SubjectMessage::SubjectChanged);
    }

    mBufferAgeQueriedSinceLastSwap = false;

    mIsDamageRegionSet = false;
}

Error Surface::initialize(const Display *display)
{
    GLenum overrideRenderTargetFormat = mState.config->renderTargetFormat;

    // To account for color space differences, override the renderTargetFormat with the
    // non-linear format. If no suitable non-linear format was found, return
    // EGL_BAD_MATCH error
    if (!gl::ColorspaceFormatOverride(mGLColorspace, &overrideRenderTargetFormat))
    {
        return egl::Error(EGL_BAD_MATCH);
    }

    // If an override is required update mState.config as well
    if (mState.config->renderTargetFormat != overrideRenderTargetFormat)
    {
        egl::Config *overrideConfig        = new egl::Config(*(mState.config));
        overrideConfig->renderTargetFormat = overrideRenderTargetFormat;
        delete mState.config;
        mState.config = overrideConfig;

        mColorFormat = gl::Format(mState.config->renderTargetFormat);
        mDSFormat    = gl::Format(mState.config->depthStencilFormat);
    }

    ANGLE_TRY(mImplementation->initialize(display));

    // Initialized here since impl is nullptr in the constructor.
    // Must happen after implementation initialize for Android.
    mState.swapBehavior = mImplementation->getSwapBehavior();

    // Update render buffer based on what the impl supports.
    if ((mType == EGL_WINDOW_BIT) && mRenderBuffer == EGL_SINGLE_BUFFER &&
        !mImplementation->supportsSingleRenderBuffer())
    {
        mRenderBuffer = EGL_BACK_BUFFER;
    }

    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));

        // GL_RGBA + GL_HALF_FLOAT is not a valid format/type combination in GLES like it is in
        // desktop GL. Adjust the frontend format to be sized RGBA16F.
        if (internalFormat == GL_RGBA && type == GL_HALF_FLOAT)
        {
            internalFormat = GL_RGBA16F;
        }
        mColorFormat = gl::Format(internalFormat, type);
    }
    if (mBuftype == EGL_D3D_TEXTURE_ANGLE)
    {
        const angle::Format *colorFormat = mImplementation->getClientBufferTextureColorFormat();
        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();
    }

    mImplObserverBinding.bind(mImplementation);

    return NoError();
}

Error Surface::makeCurrent(const gl::Context *context)
{
    if (isLocked())
    {
        return egl::Error(EGL_BAD_ACCESS);
    }
    ANGLE_TRY(mImplementation->makeCurrent(context));
    mIsCurrentOnAnyContext = true;
    addRef();
    return NoError();
}

Error Surface::unMakeCurrent(const gl::Context *context)
{
    ANGLE_TRY(mImplementation->unMakeCurrent(context));
    mIsCurrentOnAnyContext = false;
    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::prepareSwap(const gl::Context *context)
{
    ANGLE_TRACE_EVENT0("gpu.angle", "egl::Surface::prepareSwap");
    return mImplementation->prepareSwap(context);
}

Error Surface::swap(gl::Context *context)
{
    ANGLE_TRACE_EVENT0("gpu.angle", "egl::Surface::swap");
    context->onPreSwap();

    context->getState().getOverlay()->onSwap();

    ANGLE_TRY(updatePropertiesOnSwap(context));

    rx::SurfaceSwapFeedback feedback;
    ANGLE_TRY_WITH_FINALLY(mImplementation->swap(context, &feedback), postSwap(context, feedback));
    return NoError();
}

Error Surface::swapWithDamage(gl::Context *context, const EGLint *rects, EGLint n_rects)
{
    ANGLE_TRACE_EVENT0("gpu.angle", "egl::Surface::swapWithDamage");
    context->onPreSwap();

    context->getState().getOverlay()->onSwap();

    ANGLE_TRY(updatePropertiesOnSwap(context));

    rx::SurfaceSwapFeedback feedback;
    ANGLE_TRY_WITH_FINALLY(mImplementation->swapWithDamage(context, rects, n_rects, &feedback),
                           postSwap(context, feedback));
    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();
    }

    context->getState().getOverlay()->onSwap();

    ANGLE_TRY(updatePropertiesOnSwap(context));
    ANGLE_TRY(mImplementation->postSubBuffer(context, x, y, width, height));
    rx::SurfaceSwapFeedback feedback;
    postSwap(context, feedback);
    return NoError();
}

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::setRequestedSwapInterval(EGLint interval)
{
    mRequestedSwapInterval = interval;
}

void Surface::setSwapInterval(const Display *display, EGLint interval)
{
    mImplementation->setSwapInterval(display, interval);
    mState.swapInterval = 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();
    mState.swapBehavior = 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::getRequestedRenderBuffer() const
{
    return mRequestedRenderBuffer;
}

EGLenum Surface::getSwapBehavior() const
{
    return mState.swapBehavior;
}

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;
}

gl::Extents Surface::getSize() const
{
    return mFixedSize
               ? gl::Extents(static_cast<EGLint>(mFixedWidth), static_cast<EGLint>(mFixedHeight), 1)
               : mImplementation->getSize();
}

egl::Error Surface::getUserSize(const egl::Display *display, EGLint *width, EGLint *height) const
{
    ASSERT(width != nullptr || height != nullptr);
    if (mFixedSize)
    {
        if (width != nullptr)
        {
            *width = static_cast<EGLint>(mFixedWidth);
        }
        if (height != nullptr)
        {
            *height = static_cast<EGLint>(mFixedHeight);
        }
        return NoError();
    }
    else
    {
        return mImplementation->getUserSize(display, width, height);
    }
}

Error Surface::bindTexImage(gl::Context *context, gl::Texture *texture, EGLint buffer)
{
    ASSERT(!mTexture);
    ANGLE_TRY(mImplementation->bindTexImage(context, texture, buffer));
    Surface *previousSurface = texture->getBoundSurface();
    if (previousSurface != nullptr)
    {
        ANGLE_TRY(previousSurface->releaseTexImage(context, buffer));
    }
    if (texture->bindTexImageFromSurface(context, this) == angle::Result::Stop)
    {
        return Error(EGL_BAD_SURFACE);
    }
    mTexture = texture;
    addRef();

    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::getMscRate(EGLint *numerator, EGLint *denominator)
{
    return mImplementation->getMscRate(numerator, denominator);
}

Error Surface::releaseTexImageFromTexture(const gl::Context *context)
{
    ASSERT(mTexture);
    mTexture = nullptr;
    return releaseRef(context->getDisplay());
}

angle::Result Surface::ensureSizeResolved(const gl::Context *context) const
{
    return mImplementation->ensureSizeResolved(context);
}

bool Surface::isAttachmentSpecified(const gl::ImageIndex & /*imageIndex*/) const
{
    // Surface is always specified even if it has 0 sizes.
    return true;
}

gl::Extents Surface::getAttachmentSize(const gl::ImageIndex & /*target*/) const
{
    return getSize();
}

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;
}

bool Surface::isYUV() const
{
    // EGL_EXT_yuv_surface is not implemented.
    return false;
}

bool Surface::isExternalImageWithoutIndividualSync() const
{
    return false;
}

bool Surface::hasFrontBufferUsage() const
{
    return false;
}

GLuint Surface::getId() const
{
    return mState.id.value;
}

Error Surface::getBufferAgeImpl(const gl::Context *context, EGLint *age) const
{
    // When EGL_BUFFER_PRESERVED, the previous frame contents are copied to
    // current frame, so the buffer age is always 1.
    if (mState.swapBehavior == EGL_BUFFER_PRESERVED)
    {
        if (age != nullptr)
        {
            *age = 1;
        }
        return egl::NoError();
    }
    return mImplementation->getBufferAge(context, age);
}

Error Surface::getBufferAge(const gl::Context *context, EGLint *age)
{
    Error err = getBufferAgeImpl(context, age);
    if (!err.isError())
    {
        mBufferAgeQueriedSinceLastSwap = true;
    }
    return err;
}

gl::InitState Surface::initState(GLenum binding, const gl::ImageIndex & /*imageIndex*/) const
{
    switch (binding)
    {
        case GL_BACK:
            return mColorInitState;
        case GL_DEPTH:
        case GL_STENCIL:
            return mDepthStencilInitState;
        default:
            UNREACHABLE();
            return gl::InitState::Initialized;
    }
}

void Surface::setInitState(GLenum binding,
                           const gl::ImageIndex & /*imageIndex*/,
                           gl::InitState initState)
{
    switch (binding)
    {
        case GL_BACK:
            mColorInitState = initState;
            break;
        case GL_DEPTH:
        case GL_STENCIL:
            mDepthStencilInitState = initState;
            break;
        default:
            UNREACHABLE();
            break;
    }
}

void Surface::setTimestampsEnabled(bool enabled)
{
    mImplementation->setTimestampsEnabled(enabled);
    mState.timestampsEnabled = enabled;
}

bool Surface::isTimestampsEnabled() const
{
    return mState.timestampsEnabled;
}

Error Surface::setAutoRefreshEnabled(bool enabled)
{
    ANGLE_TRY(mImplementation->setAutoRefreshEnabled(enabled));
    mState.autoRefreshEnabled = enabled;
    return NoError();
}

bool Surface::hasProtectedContent() const
{
    return mState.hasProtectedContent();
}

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);
}

void Surface::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
{
    ASSERT(index == kSurfaceImplSubjectIndex);
    switch (message)
    {
        case angle::SubjectMessage::SubjectChanged:
            onStateChange(angle::SubjectMessage::ContentsChanged);
            break;
        case angle::SubjectMessage::SurfaceChanged:
            onStateChange(angle::SubjectMessage::SurfaceChanged);
            break;
        default:
            UNREACHABLE();
            break;
    }
}

Error Surface::setRenderBuffer(EGLint renderBuffer)
{
    ANGLE_TRY(mImplementation->setRenderBuffer(renderBuffer));
    mRenderBuffer = renderBuffer;
    return NoError();
}

void Surface::setRequestedRenderBuffer(EGLint requestedRenderBuffer)
{
    mRequestedRenderBuffer = requestedRenderBuffer;
}

Error Surface::updatePropertiesOnSwap(const gl::Context *context)
{
    if ((mRenderBuffer != mRequestedRenderBuffer) &&
        context->getDisplay()->getExtensions().mutableRenderBufferKHR &&
        (getConfig()->surfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR))
    {
        ANGLE_TRY(setRenderBuffer(mRequestedRenderBuffer));
    }
    if (mState.swapInterval != mRequestedSwapInterval)
    {
        setSwapInterval(context->getDisplay(), mRequestedSwapInterval);
    }
    return NoError();
}

bool Surface::isLocked() const
{
    return (mLockBufferPtr != nullptr);
}

EGLint Surface::getBitmapPitch() const
{
    return mLockBufferPitch;
}

EGLint Surface::getBitmapOrigin() const
{
    return mImplementation->origin();
}

EGLint Surface::getRedOffset() const
{
    const gl::InternalFormat &format = *mColorFormat.info;
    if (gl::IsBGRAFormat(format.internalFormat))
    {
        return format.blueBits + format.greenBits;
    }
    else
    {
        return 0;
    }
}

EGLint Surface::getGreenOffset() const
{
    const gl::InternalFormat &format = *mColorFormat.info;
    if (gl::IsBGRAFormat(format.internalFormat))
    {
        return format.blueBits;
    }
    else
    {
        return format.redBits;
    }
}

EGLint Surface::getBlueOffset() const
{
    const gl::InternalFormat &format = *mColorFormat.info;
    if (gl::IsBGRAFormat(format.internalFormat))
    {
        return 0;
    }
    else
    {
        return format.redBits + format.greenBits;
    }
}

EGLint Surface::getAlphaOffset() const
{
    const gl::InternalFormat &format = *mColorFormat.info;
    if (format.isLUMA())
    {
        return format.luminanceBits;  // Luma always first, alpha optional
    }
    // For RGBA/BGRA alpha is last
    return format.blueBits + format.greenBits + format.redBits;
}

EGLint Surface::getLuminanceOffset() const
{
    return 0;
}

EGLint Surface::getBitmapPixelSize() const
{
    constexpr EGLint kBitsPerByte    = 8;
    const gl::InternalFormat &format = *mColorFormat.info;
    return (format.pixelBytes * kBitsPerByte);
}

EGLAttribKHR Surface::getBitmapPointer() const
{
    return static_cast<EGLAttribKHR>((intptr_t)mLockBufferPtr);
}

egl::Error Surface::getCompressionRate(const egl::Display *display,
                                       const gl::Context *context,
                                       EGLint *rate)
{
    return mImplementation->getCompressionRate(display, context, rate);
}

egl::Error Surface::lockSurfaceKHR(const egl::Display *display, const AttributeMap &attributes)
{
    EGLint lockBufferUsageHint = attributes.getAsInt(
        EGL_LOCK_USAGE_HINT_KHR, (EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR));

    bool preservePixels = ((attributes.getAsInt(EGL_MAP_PRESERVE_PIXELS_KHR, false) == EGL_TRUE) ||
                           (mState.swapBehavior == EGL_BUFFER_PRESERVED));

    return mImplementation->lockSurface(display, lockBufferUsageHint, preservePixels,
                                        &mLockBufferPtr, &mLockBufferPitch);
}

egl::Error Surface::unlockSurfaceKHR(const egl::Display *display)
{
    mLockBufferPtr   = nullptr;
    mLockBufferPitch = 0;
    return mImplementation->unlockSurface(display, true);
}

WindowSurface::WindowSurface(rx::EGLImplFactory *implFactory,
                             SurfaceID id,
                             const egl::Config *config,
                             EGLNativeWindowType window,
                             const AttributeMap &attribs,
                             bool robustResourceInit)
    : Surface(EGL_WINDOW_BIT, id, config, attribs, robustResourceInit)
{
    mImplementation = implFactory->createWindowSurface(mState, window, attribs);
}

void Surface::setDamageRegion(const EGLint *rects, EGLint n_rects)
{
    mIsDamageRegionSet = true;
}

WindowSurface::~WindowSurface() {}

PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
                               SurfaceID id,
                               const Config *config,
                               const AttributeMap &attribs,
                               bool robustResourceInit)
    : Surface(EGL_PBUFFER_BIT, id, config, attribs, robustResourceInit)
{
    mImplementation = implFactory->createPbufferSurface(mState, attribs);
}

PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
                               SurfaceID id,
                               const Config *config,
                               EGLenum buftype,
                               EGLClientBuffer clientBuffer,
                               const AttributeMap &attribs,
                               bool robustResourceInit)
    : Surface(EGL_PBUFFER_BIT, id, config, attribs, robustResourceInit, buftype)
{
    mImplementation =
        implFactory->createPbufferFromClientBuffer(mState, buftype, clientBuffer, attribs);
}

PbufferSurface::~PbufferSurface() {}

PixmapSurface::PixmapSurface(rx::EGLImplFactory *implFactory,
                             SurfaceID id,
                             const Config *config,
                             NativePixmapType nativePixmap,
                             const AttributeMap &attribs,
                             bool robustResourceInit)
    : Surface(EGL_PIXMAP_BIT, id, config, attribs, robustResourceInit)
{
    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
