mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-11-07 01:53:24 +09:00
131 lines
8.2 KiB
C++
131 lines
8.2 KiB
C++
// MobileGL - MobileGL/MG_Backend/DirectGLES/BackendObject_DirectGLES.h
|
|
// Copyright (c) 2025-2026 MobileGL-Dev
|
|
// Licensed under the GNU Lesser General Public License v3.0:
|
|
// https://www.gnu.org/licenses/gpl-3.0.txt
|
|
// https://www.gnu.org/licenses/lgpl-3.0.txt
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
// End of Source File Header
|
|
|
|
#pragma once
|
|
#include <Includes.h>
|
|
#include "../BackendObject.h"
|
|
#include <MG_Util/BackendLoaders/OpenGL/Loader.h>
|
|
|
|
namespace MobileGL::MG_Backend::DirectGLES {
|
|
// Populates the same format-capability cache used by backend startup. The caller
|
|
// must keep the supplied GLES context current for the duration of this call.
|
|
void PopulateFormatCapabilities(const MG_External::GLESFunctionsTable& gl,
|
|
const MG_External::GLESCapabilities& capabilities,
|
|
FormatCapabilityCache& cache);
|
|
|
|
// Clamps a requested sample count down to what the ES driver can really deliver for this
|
|
// format on this format-capability target: the probed per-format list when there is one, the
|
|
// driver's per-class GL_MAX_*_SAMPLES otherwise. The frontend deliberately validates against
|
|
// the count MobileGL advertises instead (GL_Getter's GetAdvertisedMaxSamples), which on a
|
|
// driver reporting GL_MAX_INTEGER_SAMPLES 1 is higher than the driver accepts, so every ES
|
|
// allocation call has to come through here. The shadow state keeps the requested count, so
|
|
// GL_TEXTURE_SAMPLES and framebuffer completeness still answer what the application asked for.
|
|
Int ClampSamplesToBackendSupport(SizeT targetIndex, TextureInternalFormat logicalFormat, GLenum imageFormat,
|
|
Int samples);
|
|
|
|
class BackendObject_DirectGLES : public BackendObject {
|
|
public:
|
|
~BackendObject_DirectGLES() override;
|
|
|
|
// The driver's verdict on this session's context (DirectGLES::LatchIfDeviceLost).
|
|
Bool LatchIfGpuFaulted() override;
|
|
void Initialize() override;
|
|
Bool InitCapabilities() override;
|
|
Bool InitWindowSurface() override;
|
|
Bool InitializeEGLDisplay(EGLDisplay dpy, EGLint* major, EGLint* minor) override;
|
|
Bool CreateEGLWindowSurface(EGLSurface surface, const WindowHandle& handle) override;
|
|
Bool CreateEGLPbufferSurface(EGLSurface surface, EGLint width, EGLint height) override;
|
|
Bool ResizeEGLWindowSurface(EGLSurface surface, Uint32 width, Uint32 height) override;
|
|
Bool MakeEGLCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) override;
|
|
Bool SwapEGLBuffers(EGLDisplay dpy, EGLSurface draw) override;
|
|
// Shared images: a GL blit of default framebuffer 0 into a renderbuffer whose storage is
|
|
// the image's EGLImage, ordered after the image's pending reads and published as a native
|
|
// fence without a CPU wait (DirectGLES.h, SharedImageImpl).
|
|
Bool BlitDefaultFramebufferToSharedImage(const SharedImageView& image,
|
|
const MG_Util::Damage::Region& region) override;
|
|
// A window surface's age is the driver's (EGL_EXT_buffer_age); a pbuffer keeps its content,
|
|
// so it is 1 once it has been presented (DirectGLES::CurrentDrawBufferAge).
|
|
Int32 QueryCurrentBufferAge(Bool damageRegionFollows) override;
|
|
// eglSetDamageRegionKHR on a window surface whose driver has EGL_KHR_partial_update.
|
|
Bool SetCurrentDamageRegion(const MG_Util::Damage::Region& region) override;
|
|
// A glFlush that ends a shared-image producer's frame (SharedImageImpl::PublishPendingAccesses).
|
|
Bool PublishSharedImageAccesses() override;
|
|
// An EGL native fence of the session's work (SharedImageImpl::ExportNativeFence).
|
|
Bool ExportNativeFence(int* fence) override;
|
|
void ReleaseEGLSurface(EGLSurface surface) override;
|
|
void ReleaseEGLResources() override;
|
|
// The server window going and coming back: each window surface on it swaps its native EGL
|
|
// window surface for a placeholder pbuffer and back (DirectGLES::Suspend/ResumeSessionWindowSurface).
|
|
Bool SuspendServerWindow(void* window) override;
|
|
Bool ResumeServerWindow(void* window, Uint32 width, Uint32 height) override;
|
|
Bool ServerWindowResized(void* window, Uint32 width, Uint32 height) override;
|
|
|
|
const RendererInfo& GetRendererInfo() const override;
|
|
String GetBackendAPIVersionString() const override;
|
|
const GlobalBackendFunctionsTable& GetBackendFunctions() const override;
|
|
const DynamicBackendParameters& GetDynamicParameters() const override;
|
|
BackendType GetBackendType() const override;
|
|
|
|
const MG_External::GLESFunctionsTable& GetGLESFunctions() const;
|
|
const MG_External::EGLFunctionsTable& GetEGLFunctions() const;
|
|
void ApplyGLESCapabilitiesForTesting(const MG_External::GLESCapabilities& capabilities);
|
|
|
|
private:
|
|
void UpdateDynamicBackendParameters();
|
|
Bool InitPbufferSurface(EGLint width, EGLint height) override;
|
|
void OnEGLSurfaceReleased(EGLSurface surface) override;
|
|
void OnEGLSurfaceForgotten(EGLSurface surface) override;
|
|
// An existing native surface for the client surface being activated, re-bound; false when
|
|
// there is none yet (the caller creates it).
|
|
Bool RebindNativeSurfaceFor(EGLSurface surface);
|
|
// EGL: creating a surface does not change what is current. The creation bound the new
|
|
// surface natively; put the previous one back for the context that held it.
|
|
void RestoreSurfaceAfterCreation(EGLSurface previousNativeDraw);
|
|
|
|
Bool m_initialized = false;
|
|
// P14: ONE NATIVE SURFACE PER CLIENT SURFACE, created on its first activation and re-bound
|
|
// on every later one. A multi-window client switches surfaces every frame; making a new
|
|
// native surface each time leaked them and lost what the window had drawn.
|
|
UnorderedMap<EGLSurface, EGLSurface> m_nativeSurfaces;
|
|
// Window surfaces whose window is gone (SuspendServerWindow): their native surface is a
|
|
// placeholder pbuffer until ResumeServerWindow.
|
|
Vector<EGLSurface> m_suspendedWindowSurfaces;
|
|
MG_External::EGLFunctionsTable m_EGLFunctions;
|
|
MG_External::GLESFunctionsTable m_GLESFunctions;
|
|
MG_External::GLESCapabilities m_GLESCapabilities;
|
|
DynamicBackendParameters m_dynamicParameters;
|
|
};
|
|
|
|
// Single-source-of-truth helpers shared with the driver POST
|
|
// (MG_Util/SelfTest/DriverPost.cpp), so the identity strings and extension list
|
|
// MobileGL reports to applications on this backend cannot drift from what the
|
|
// POST screen shows.
|
|
|
|
// Static identity of the Espryt renderer (renderer/backend names, target GL/GLSL
|
|
// versions, ExtraVendor). The Extensions vector inside is live backend state that
|
|
// is reconciled after capability init; callers that need the advertised list for
|
|
// a known capability set must use BuildAdvertisedExtensions instead.
|
|
const RendererInfo& GetRendererIdentity();
|
|
|
|
// The full OpenGL extension list Espryt advertises (glGetString(GL_EXTENSIONS))
|
|
// for a device whose timer queries / anisotropic filtering / native indirect draws /
|
|
// non-zero indirect baseInstance semantics / EXT-OES texture views are (or are not) usable,
|
|
// plus the feature set in `features`. The MOBILEGL_DISABLE_TIMERQUERY escape hatch is applied
|
|
// inside.
|
|
Vector<GLExtension> BuildAdvertisedExtensions(Bool timerQueriesSupported, Bool anisotropicFilteringSupported,
|
|
Bool drawIndirectSupported,
|
|
Bool nonZeroIndirectBaseInstanceSupported,
|
|
Bool textureViewSupported, Bool cubeMapArraySupported,
|
|
const AdvertisedFeatureSupport& features = {});
|
|
|
|
// Format: <OpenGL ES Renderer>, OpenGL ES <Major>.<Minor> — the exact string an
|
|
// initialized backend returns from GetBackendAPIVersionString (and that ends up
|
|
// inside the application-visible GL_RENDERER string).
|
|
String FormatBackendAPIVersionString(const String& glesRendererString, Int glesMajor, Int glesMinor);
|
|
} // namespace MobileGL::MG_Backend::DirectGLES
|