// // 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 #include #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; using SupportedTimestamps = angle::PackedEnumBitSet; 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. // https://issuetracker.google.com/issues/153329980 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; } // namespace egl #endif // LIBANGLE_SURFACE_H_