Source code
Revision control
Copy as Markdown
Other Tools
//
// 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.h: Defines 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.
#ifndef LIBANGLE_SURFACE_H_
#define LIBANGLE_SURFACE_H_
#include <memory>
#include <EGL/egl.h>
#include "common/PackedEnums.h"
#include "common/angleutils.h"
#include "libANGLE/AttributeMap.h"
#include "libANGLE/Debug.h"
#include "libANGLE/Error.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/RefCountObject.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/SurfaceImpl.h"
namespace gl
{
class Context;
class Framebuffer;
class Texture;
} // namespace gl
namespace rx
{
class EGLImplFactory;
}
namespace egl
{
class Display;
struct Config;
using SupportedCompositorTiming = angle::PackedEnumBitSet<CompositorTiming>;
using SupportedTimestamps = angle::PackedEnumBitSet<Timestamp>;
struct SurfaceState final : private angle::NonCopyable
{
SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn);
~SurfaceState();
bool isRobustResourceInitEnabled() const;
bool hasProtectedContent() const;
EGLint getPreferredSwapInterval() const;
EGLLabelKHR label;
const egl::Config *config;
AttributeMap attributes;
bool timestampsEnabled;
bool autoRefreshEnabled;
SupportedCompositorTiming supportedCompositorTimings;
SupportedTimestamps supportedTimestamps;
bool directComposition;
EGLenum swapBehavior;
};
class Surface : public LabeledObject, public gl::FramebufferAttachmentObject
{
public:
rx::SurfaceImpl *getImplementation() const { return mImplementation; }
void setLabel(EGLLabelKHR label) override;
EGLLabelKHR getLabel() const override;
EGLint getType() const;
Error initialize(const Display *display);
Error makeCurrent(const gl::Context *context);
Error unMakeCurrent(const gl::Context *context);
Error prepareSwap(const gl::Context *context);
Error swap(const gl::Context *context);
Error swapWithDamage(const gl::Context *context, const EGLint *rects, EGLint n_rects);
Error swapWithFrameToken(const gl::Context *context, EGLFrameTokenANGLE frameToken);
Error postSubBuffer(const gl::Context *context,
EGLint x,
EGLint y,
EGLint width,
EGLint height);
Error setPresentationTime(EGLnsecsANDROID time);
Error querySurfacePointerANGLE(EGLint attribute, void **value);
Error bindTexImage(gl::Context *context, gl::Texture *texture, EGLint buffer);
Error releaseTexImage(const gl::Context *context, EGLint buffer);
Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc);
Error getMscRate(EGLint *numerator, EGLint *denominator);
EGLint isPostSubBufferSupported() const;
void setSwapInterval(EGLint interval);
Error onDestroy(const Display *display);
void setMipmapLevel(EGLint level);
void setMultisampleResolve(EGLenum resolve);
void setSwapBehavior(EGLenum behavior);
void setFixedWidth(EGLint width);
void setFixedHeight(EGLint height);
const Config *getConfig() const;
// width and height can change with client window resizing
EGLint getWidth() const;
EGLint getHeight() const;
// Note: windows cannot be resized on Android. The approach requires
// calling vkGetPhysicalDeviceSurfaceCapabilitiesKHR. However, that is
// expensive; and there are troublesome timing issues for other parts of
// ANGLE (which cause test failures and crashes). Therefore, a
// special-Android-only path is created just for the querying of EGL_WIDTH
// and EGL_HEIGHT.
egl::Error getUserWidth(const egl::Display *display, EGLint *value) const;
egl::Error getUserHeight(const egl::Display *display, EGLint *value) const;
EGLint getPixelAspectRatio() const;
EGLenum getRenderBuffer() const;
EGLenum getSwapBehavior() const;
TextureFormat getTextureFormat() const;
EGLenum getTextureTarget() const;
bool getLargestPbuffer() const;
EGLenum getGLColorspace() const;
EGLenum getVGAlphaFormat() const;
EGLenum getVGColorspace() const;
bool getMipmapTexture() const;
EGLint getMipmapLevel() const;
EGLint getHorizontalResolution() const;
EGLint getVerticalResolution() const;
EGLenum getMultisampleResolve() const;
bool hasProtectedContent() const override;
// For lock surface buffer
EGLint getBitmapPitch() const;
EGLint getBitmapOrigin() const;
EGLint getRedOffset() const;
EGLint getGreenOffset() const;
EGLint getBlueOffset() const;
EGLint getAlphaOffset() const;
EGLint getLuminanceOffset() const;
EGLint getBitmapPixelSize() const;
EGLAttribKHR getBitmapPointer() const;
egl::Error lockSurfaceKHR(const egl::Display *display, const AttributeMap &attributes);
egl::Error unlockSurfaceKHR(const egl::Display *display);
bool isLocked() const;
bool isCurrentOnAnyContext() const { return mIsCurrentOnAnyContext; }
gl::Texture *getBoundTexture() const { return mTexture; }
EGLint isFixedSize() const;
// FramebufferAttachmentObject implementation
gl::Extents getAttachmentSize(const gl::ImageIndex &imageIndex) const override;
gl::Format getAttachmentFormat(GLenum binding, const gl::ImageIndex &imageIndex) const override;
GLsizei getAttachmentSamples(const gl::ImageIndex &imageIndex) const override;
bool isRenderable(const gl::Context *context,
GLenum binding,
const gl::ImageIndex &imageIndex) const override;
bool isYUV() const override;
bool isCreatedWithAHB() const override;
void onAttach(const gl::Context *context, rx::Serial framebufferSerial) override {}
void onDetach(const gl::Context *context, rx::Serial framebufferSerial) override {}
GLuint getId() const override;
EGLint getOrientation() const { return mOrientation; }
bool directComposition() const { return mState.directComposition; }
gl::InitState initState(GLenum binding, const gl::ImageIndex &imageIndex) const override;
void setInitState(GLenum binding,
const gl::ImageIndex &imageIndex,
gl::InitState initState) override;
bool isRobustResourceInitEnabled() const { return mRobustResourceInitialization; }
const gl::Format &getBindTexImageFormat() const { return mColorFormat; }
// EGL_ANDROID_get_frame_timestamps entry points
void setTimestampsEnabled(bool enabled);
bool isTimestampsEnabled() const;
// EGL_ANDROID_front_buffer_auto_refresh entry points
Error setAutoRefreshEnabled(bool enabled);
const SupportedCompositorTiming &getSupportedCompositorTimings() const;
Error getCompositorTiming(EGLint numTimestamps,
const EGLint *names,
EGLnsecsANDROID *values) const;
Error getNextFrameId(EGLuint64KHR *frameId) const;
const SupportedTimestamps &getSupportedTimestamps() const;
Error getFrameTimestamps(EGLuint64KHR frameId,
EGLint numTimestamps,
const EGLint *timestamps,
EGLnsecsANDROID *values) const;
// Returns the offset into the texture backing the surface if specified via texture offset
// attributes (see EGL_ANGLE_d3d_texture_client_buffer extension). Returns zero offset
// otherwise.
const gl::Offset &getTextureOffset() const { return mTextureOffset; }
Error getBufferAge(const gl::Context *context, EGLint *age);
Error setRenderBuffer(EGLint renderBuffer);
bool bufferAgeQueriedSinceLastSwap() const { return mBufferAgeQueriedSinceLastSwap; }
void setDamageRegion(const EGLint *rects, EGLint n_rects);
bool isDamageRegionSet() const { return mIsDamageRegionSet; }
void addRef() { mRefCount++; }
void release()
{
ASSERT(mRefCount > 0);
mRefCount--;
}
protected:
Surface(EGLint surfaceType,
GLuint serialId,
const egl::Config *config,
const AttributeMap &attributes,
bool forceRobustResourceInit,
EGLenum buftype = EGL_NONE);
~Surface() override;
rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
// ANGLE-only method, used internally
friend class gl::Texture;
Error releaseTexImageFromTexture(const gl::Context *context);
SurfaceState mState;
rx::SurfaceImpl *mImplementation;
int mRefCount;
bool mDestroyed;
EGLint mType;
EGLenum mBuftype;
bool mPostSubBufferRequested;
bool mLargestPbuffer;
EGLenum mGLColorspace;
EGLenum mVGAlphaFormat;
EGLenum mVGColorspace;
bool mMipmapTexture;
EGLint mMipmapLevel;
EGLint mHorizontalResolution;
EGLint mVerticalResolution;
EGLenum mMultisampleResolve;
bool mFixedSize;
size_t mFixedWidth;
size_t mFixedHeight;
bool mRobustResourceInitialization;
TextureFormat mTextureFormat;
EGLenum mTextureTarget;
EGLint mPixelAspectRatio; // Display aspect ratio
EGLenum mRenderBuffer; // Render buffer
EGLint mOrientation;
// We don't use a binding pointer here. We don't ever want to own an orphaned texture. If a
// Texture is deleted the Surface is unbound in onDestroy.
gl::Texture *mTexture;
gl::Format mColorFormat;
gl::Format mDSFormat;
gl::Offset mTextureOffset;
bool mIsCurrentOnAnyContext; // The surface is current to a context/client API
uint8_t *mLockBufferPtr; // Memory owned by backend.
EGLint mLockBufferPitch;
bool mBufferAgeQueriedSinceLastSwap;
bool mIsDamageRegionSet;
private:
Error getBufferAgeImpl(const gl::Context *context, EGLint *age) const;
Error destroyImpl(const Display *display);
void postSwap(const gl::Context *context);
Error releaseRef(const Display *display);
// ObserverInterface implementation.
void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
gl::InitState mColorInitState;
gl::InitState mDepthStencilInitState;
angle::ObserverBinding mImplObserverBinding;
GLuint mSerialId;
};
class WindowSurface final : public Surface
{
public:
WindowSurface(rx::EGLImplFactory *implFactory,
const Config *config,
EGLNativeWindowType window,
const AttributeMap &attribs,
bool robustResourceInit);
~WindowSurface() override;
};
class PbufferSurface final : public Surface
{
public:
PbufferSurface(rx::EGLImplFactory *implFactory,
const Config *config,
const AttributeMap &attribs,
bool robustResourceInit);
PbufferSurface(rx::EGLImplFactory *implFactory,
const Config *config,
EGLenum buftype,
EGLClientBuffer clientBuffer,
const AttributeMap &attribs,
bool robustResourceInit);
protected:
~PbufferSurface() override;
};
class PixmapSurface final : public Surface
{
public:
PixmapSurface(rx::EGLImplFactory *implFactory,
const Config *config,
NativePixmapType nativePixmap,
const AttributeMap &attribs,
bool robustResourceInit);
protected:
~PixmapSurface() override;
};
class [[nodiscard]] ScopedSurfaceRef
{
public:
ScopedSurfaceRef(Surface *surface) : mSurface(surface)
{
if (mSurface)
{
mSurface->addRef();
}
}
~ScopedSurfaceRef()
{
if (mSurface)
{
mSurface->release();
}
}
private:
Surface *const mSurface;
};
class SurfaceDeleter final
{
public:
SurfaceDeleter(const Display *display);
~SurfaceDeleter();
void operator()(Surface *surface);
private:
const Display *mDisplay;
};
using SurfacePointer = std::unique_ptr<Surface, SurfaceDeleter>;
} // namespace egl
#endif // LIBANGLE_SURFACE_H_