mirror of
https://github.com/mitch030504/AstroQuest-Frame.git
synced 2026-10-28 01:00:49 +01:00
Work of 2026-10-04, committed as it was (README-QUEST-VR.md tells each step): - 0.14: every start shows a panel in the headset to choose how much of the field of view the game draws (left and right on the D-pad or the left stick, X to play). Less is the same pixels over fewer degrees, a sharper picture; the choice is remembered. Below all of it, each eye gets a soft-edged squircle border, drawn where the host copies the frame. - 0.15: the percent is of the headset's own view, read from OpenXR before Play is offered and handed to the emulator before the game starts (SHADPS4_VR_HEADSET_FOV_TAN), 50 to 100. - 0.16: the border sits around each eye's straight ahead, which a headset's uneven view does not have in the middle of the picture. - 0.17: both eyes draw the same, even view around straight ahead that takes in the headset's own (SHADPS4_VR_FOV_SYMMETRIC), so that what one eye shows the other shows too when the view is narrowed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
87 lines
3.0 KiB
C++
87 lines
3.0 KiB
C++
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
#pragma once
|
|
|
|
// The GL side of showing the emulator's frames, shared by the OpenXR host and by the self test
|
|
// that exercises the same path without a headset session.
|
|
|
|
#include <cstdint>
|
|
#include <vector>
|
|
|
|
// Extension entry points (EGL images over hardware buffers) are only declared on request.
|
|
#define EGL_EGLEXT_PROTOTYPES
|
|
#define GL_GLEXT_PROTOTYPES
|
|
#include <EGL/egl.h>
|
|
#include <EGL/eglext.h>
|
|
#include <GLES3/gl3.h>
|
|
// The extension header relies on the types the one above defines.
|
|
#include <GLES2/gl2ext.h>
|
|
|
|
struct AHardwareBuffer;
|
|
class CoreProcess;
|
|
|
|
/// An OpenGL ES 3 context that draws to nothing: everything is rendered to textures.
|
|
struct GlContext {
|
|
EGLDisplay display{EGL_NO_DISPLAY};
|
|
EGLConfig config{};
|
|
EGLContext context{EGL_NO_CONTEXT};
|
|
EGLSurface surface{EGL_NO_SURFACE};
|
|
|
|
bool Create();
|
|
void Destroy();
|
|
};
|
|
|
|
/// The images the emulator renders into: hardware buffers handed to it as dma-bufs, each of them
|
|
/// also a GL texture here, so that a frame gets from one process to the other without a copy.
|
|
class FrameBuffers {
|
|
public:
|
|
static constexpr uint32_t Count = 3;
|
|
|
|
/// Allocates the buffers and offers them to the core. Needs a current GL context.
|
|
bool Create(EGLDisplay display, uint32_t width, uint32_t height, CoreProcess& core);
|
|
void Destroy(EGLDisplay display);
|
|
|
|
bool IsValid(uint32_t index) const {
|
|
return index < textures.size();
|
|
}
|
|
GLuint Texture(uint32_t index) const {
|
|
return textures[index];
|
|
}
|
|
|
|
private:
|
|
std::vector<AHardwareBuffer*> buffers;
|
|
std::vector<EGLImageKHR> images;
|
|
std::vector<GLuint> textures;
|
|
};
|
|
|
|
/// Copies a frame to the framebuffer that is bound, upside up and in the right color encoding.
|
|
class FrameBlitter {
|
|
public:
|
|
bool Create();
|
|
void Destroy();
|
|
|
|
/// `srgb_target` is for sRGB targets: they encode whatever is written to them, while the
|
|
/// emulator delivers values that are display-ready already. Where the GPU can be told to
|
|
/// leave that encoding out, the frame is written as it is; elsewhere it is decoded first,
|
|
/// which costs a power function per pixel.
|
|
/// `reduced_fov` rounds each eye's boundary into a feathered squircle. The game already
|
|
/// rendered the narrower projection; masking its corners preserves its pixel density.
|
|
/// `fov` is that frame's out/in/up/down tangents: the aperture follows each eye's optical
|
|
/// axis, which need not be at the centre of an asymmetric projection's texture.
|
|
void Draw(GLuint texture, uint32_t width, uint32_t height, bool swap_red_blue,
|
|
bool srgb_target, bool reduced_fov = false, const float* fov = nullptr) const;
|
|
|
|
/// Whether frames go into sRGB targets unchanged (see Draw).
|
|
bool WritesUnencoded() const {
|
|
return write_control;
|
|
}
|
|
|
|
private:
|
|
GLuint program{};
|
|
GLuint vertex_array{};
|
|
GLint uniform_swap{-1};
|
|
GLint uniform_decode{-1};
|
|
GLint uniform_mask{-1};
|
|
GLint uniform_fov{-1};
|
|
bool write_control{};
|
|
};
|