mirror of
https://github.com/gnif/LookingGlass.git
synced 2025-12-16 13:08:13 +00:00
Compare commits
3 Commits
dmabuf-tes
...
frame-timi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ee30b2308 | ||
|
|
714b1bce70 | ||
|
|
3ec632dd3c |
@@ -28,7 +28,6 @@
|
|||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/stringutils.h"
|
#include "common/stringutils.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
#include "common/option.h"
|
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@@ -130,29 +129,6 @@ static void pipewire_onPlaybackDrained(void * userdata)
|
|||||||
pw_thread_loop_unlock(pw.thread);
|
pw_thread_loop_unlock(pw.thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct Option pipewire_options[] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
.module = "pipewire",
|
|
||||||
.name = "outDevice",
|
|
||||||
.description = "The default playback device to use",
|
|
||||||
.type = OPTION_TYPE_STRING
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.module = "pipewire",
|
|
||||||
.name = "recDevice",
|
|
||||||
.description = "The default record device to use",
|
|
||||||
.type = OPTION_TYPE_STRING
|
|
||||||
},
|
|
||||||
|
|
||||||
{0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void pipewire_earlyInit(void)
|
|
||||||
{
|
|
||||||
option_register(pipewire_options);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool pipewire_init(void)
|
static bool pipewire_init(void)
|
||||||
{
|
{
|
||||||
pw_init(NULL, NULL);
|
pw_init(NULL, NULL);
|
||||||
@@ -245,8 +221,9 @@ static void pipewire_playbackSetup(int channels, int sampleRate,
|
|||||||
pw.playback.pullFn = pullFn;
|
pw.playback.pullFn = pullFn;
|
||||||
|
|
||||||
pw_thread_loop_lock(pw.thread);
|
pw_thread_loop_lock(pw.thread);
|
||||||
|
pw.playback.stream = pw_stream_new_simple(
|
||||||
struct pw_properties * props =
|
pw.loop,
|
||||||
|
"Looking Glass",
|
||||||
pw_properties_new(
|
pw_properties_new(
|
||||||
PW_KEY_NODE_NAME , "Looking Glass",
|
PW_KEY_NODE_NAME , "Looking Glass",
|
||||||
PW_KEY_MEDIA_TYPE , "Audio",
|
PW_KEY_MEDIA_TYPE , "Audio",
|
||||||
@@ -254,22 +231,7 @@ static void pipewire_playbackSetup(int channels, int sampleRate,
|
|||||||
PW_KEY_MEDIA_ROLE , "Music",
|
PW_KEY_MEDIA_ROLE , "Music",
|
||||||
PW_KEY_NODE_LATENCY , requestedNodeLatency,
|
PW_KEY_NODE_LATENCY , requestedNodeLatency,
|
||||||
NULL
|
NULL
|
||||||
);
|
),
|
||||||
|
|
||||||
const char * device = option_get_string("pipewire", "outDevice");
|
|
||||||
if (device)
|
|
||||||
{
|
|
||||||
#ifdef PW_KEY_TARGET_OBJECT
|
|
||||||
pw_properties_set(props, PW_KEY_TARGET_OBJECT, device);
|
|
||||||
#else
|
|
||||||
pw_properties_set(props, PW_KEY_NODE_TARGET, device);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
pw.playback.stream = pw_stream_new_simple(
|
|
||||||
pw.loop,
|
|
||||||
"Looking Glass",
|
|
||||||
props,
|
|
||||||
&events,
|
&events,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
@@ -487,30 +449,17 @@ static void pipewire_recordStart(int channels, int sampleRate,
|
|||||||
pw.record.stride = sizeof(uint16_t) * channels;
|
pw.record.stride = sizeof(uint16_t) * channels;
|
||||||
pw.record.pushFn = pushFn;
|
pw.record.pushFn = pushFn;
|
||||||
|
|
||||||
struct pw_properties * props =
|
pw_thread_loop_lock(pw.thread);
|
||||||
|
pw.record.stream = pw_stream_new_simple(
|
||||||
|
pw.loop,
|
||||||
|
"Looking Glass",
|
||||||
pw_properties_new(
|
pw_properties_new(
|
||||||
PW_KEY_NODE_NAME , "Looking Glass",
|
PW_KEY_NODE_NAME , "Looking Glass",
|
||||||
PW_KEY_MEDIA_TYPE , "Audio",
|
PW_KEY_MEDIA_TYPE , "Audio",
|
||||||
PW_KEY_MEDIA_CATEGORY, "Capture",
|
PW_KEY_MEDIA_CATEGORY, "Capture",
|
||||||
PW_KEY_MEDIA_ROLE , "Music",
|
PW_KEY_MEDIA_ROLE , "Music",
|
||||||
NULL
|
NULL
|
||||||
);
|
),
|
||||||
|
|
||||||
const char * device = option_get_string("pipewire", "recDevice");
|
|
||||||
if (device)
|
|
||||||
{
|
|
||||||
#ifdef PW_KEY_TARGET_OBJECT
|
|
||||||
pw_properties_set(props, PW_KEY_TARGET_OBJECT, device);
|
|
||||||
#else
|
|
||||||
pw_properties_set(props, PW_KEY_NODE_TARGET, device);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
pw_thread_loop_lock(pw.thread);
|
|
||||||
pw.record.stream = pw_stream_new_simple(
|
|
||||||
pw.loop,
|
|
||||||
"Looking Glass",
|
|
||||||
props,
|
|
||||||
&events,
|
&events,
|
||||||
NULL
|
NULL
|
||||||
);
|
);
|
||||||
@@ -594,10 +543,9 @@ static void pipewire_free(void)
|
|||||||
|
|
||||||
struct LG_AudioDevOps LGAD_PipeWire =
|
struct LG_AudioDevOps LGAD_PipeWire =
|
||||||
{
|
{
|
||||||
.name = "PipeWire",
|
.name = "PipeWire",
|
||||||
.earlyInit = pipewire_earlyInit,
|
.init = pipewire_init,
|
||||||
.init = pipewire_init,
|
.free = pipewire_free,
|
||||||
.free = pipewire_free,
|
|
||||||
.playback =
|
.playback =
|
||||||
{
|
{
|
||||||
.setup = pipewire_playbackSetup,
|
.setup = pipewire_playbackSetup,
|
||||||
|
|||||||
@@ -65,30 +65,15 @@ static const struct xdg_surface_listener xdgSurfaceListener = {
|
|||||||
static void xdgToplevelConfigure(void * data, struct xdg_toplevel * xdgToplevel,
|
static void xdgToplevelConfigure(void * data, struct xdg_toplevel * xdgToplevel,
|
||||||
int32_t width, int32_t height, struct wl_array * states)
|
int32_t width, int32_t height, struct wl_array * states)
|
||||||
{
|
{
|
||||||
wlWm.width = width;
|
wlWm.width = width;
|
||||||
wlWm.height = height;
|
wlWm.height = height;
|
||||||
wlWm.fullscreen = false;
|
wlWm.fullscreen = false;
|
||||||
wlWm.floating = true;
|
|
||||||
|
|
||||||
enum xdg_toplevel_state * state;
|
enum xdg_toplevel_state * state;
|
||||||
wl_array_for_each(state, states)
|
wl_array_for_each(state, states)
|
||||||
{
|
{
|
||||||
switch (*state)
|
if (*state == XDG_TOPLEVEL_STATE_FULLSCREEN)
|
||||||
{
|
|
||||||
case XDG_TOPLEVEL_STATE_FULLSCREEN:
|
|
||||||
wlWm.fullscreen = true;
|
wlWm.fullscreen = true;
|
||||||
// fallthrough
|
|
||||||
case XDG_TOPLEVEL_STATE_MAXIMIZED:
|
|
||||||
case XDG_TOPLEVEL_STATE_TILED_LEFT:
|
|
||||||
case XDG_TOPLEVEL_STATE_TILED_RIGHT:
|
|
||||||
case XDG_TOPLEVEL_STATE_TILED_TOP:
|
|
||||||
case XDG_TOPLEVEL_STATE_TILED_BOTTOM:
|
|
||||||
wlWm.floating = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,14 +156,5 @@ void waylandMinimize(void)
|
|||||||
|
|
||||||
void waylandShellResize(int w, int h)
|
void waylandShellResize(int w, int h)
|
||||||
{
|
{
|
||||||
if (!wlWm.floating)
|
//TODO: Implement resize for XDG.
|
||||||
return;
|
|
||||||
|
|
||||||
wlWm.width = w;
|
|
||||||
wlWm.height = h;
|
|
||||||
xdg_surface_set_window_geometry(wlWm.xdgSurface, 0, 0, w, h);
|
|
||||||
|
|
||||||
wlWm.needsResize = true;
|
|
||||||
app_invalidateWindow(true);
|
|
||||||
waylandStopWaitFrame();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,16 +71,12 @@ static bool waylandProbe(void)
|
|||||||
static bool waylandInit(const LG_DSInitParams params)
|
static bool waylandInit(const LG_DSInitParams params)
|
||||||
{
|
{
|
||||||
memset(&wlWm, 0, sizeof(wlWm));
|
memset(&wlWm, 0, sizeof(wlWm));
|
||||||
|
|
||||||
wlWm.display = wl_display_connect(NULL);
|
|
||||||
if (!wlWm.display)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
wl_list_init(&wlWm.surfaceOutputs);
|
wl_list_init(&wlWm.surfaceOutputs);
|
||||||
|
|
||||||
wlWm.warpSupport = option_get_bool("wayland", "warpSupport");
|
wlWm.warpSupport = option_get_bool("wayland", "warpSupport");
|
||||||
wlWm.useFractionalScale = option_get_bool("wayland", "fractionScale");
|
wlWm.useFractionalScale = option_get_bool("wayland", "fractionScale");
|
||||||
|
|
||||||
|
wlWm.display = wl_display_connect(NULL);
|
||||||
wlWm.width = params.w;
|
wlWm.width = params.w;
|
||||||
wlWm.height = params.h;
|
wlWm.height = params.h;
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,6 @@ struct WaylandDSState
|
|||||||
bool fractionalScale;
|
bool fractionalScale;
|
||||||
bool needsResize;
|
bool needsResize;
|
||||||
bool fullscreen;
|
bool fullscreen;
|
||||||
bool floating;
|
|
||||||
uint32_t resizeSerial;
|
uint32_t resizeSerial;
|
||||||
bool configured;
|
bool configured;
|
||||||
bool warpSupport;
|
bool warpSupport;
|
||||||
|
|||||||
@@ -242,31 +242,12 @@ out:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int x11ErrorHandler(Display * display, XErrorEvent * error)
|
|
||||||
{
|
|
||||||
char errorText[1024];
|
|
||||||
XGetErrorText(display, error->error_code, errorText, sizeof(errorText));
|
|
||||||
|
|
||||||
DEBUG_ERROR("X11 Error: %s", errorText);
|
|
||||||
DEBUG_PRINT_BACKTRACE();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int x11IOErrorHandler(Display * display)
|
|
||||||
{
|
|
||||||
DEBUG_FATAL("Fatal X11 IO Error");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool x11Init(const LG_DSInitParams params)
|
static bool x11Init(const LG_DSInitParams params)
|
||||||
{
|
{
|
||||||
XIDeviceInfo *devinfo;
|
XIDeviceInfo *devinfo;
|
||||||
int count;
|
int count;
|
||||||
int event, error;
|
int event, error;
|
||||||
|
|
||||||
XSetErrorHandler(x11ErrorHandler);
|
|
||||||
XSetIOErrorHandler(x11IOErrorHandler);
|
|
||||||
|
|
||||||
memset(&x11, 0, sizeof(x11));
|
memset(&x11, 0, sizeof(x11));
|
||||||
x11.xValuator = -1;
|
x11.xValuator = -1;
|
||||||
x11.yValuator = -1;
|
x11.yValuator = -1;
|
||||||
@@ -1171,46 +1152,6 @@ static void x11XInputEvent(XGenericEventCookie *cookie)
|
|||||||
app_updateCursorPos(xie->event_x, xie->event_y);
|
app_updateCursorPos(xie->event_x, xie->event_y);
|
||||||
app_handleEnterEvent(false);
|
app_handleEnterEvent(false);
|
||||||
x11.entered = false;
|
x11.entered = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* Because there is a race with the pointer ungrab the enter event for the
|
|
||||||
* next window is sometimes sent with the mode NotifyUngrab, unfortunatly
|
|
||||||
* some window managers such as i3 will ignore these which breaks focus
|
|
||||||
* follows mouse mode. To correct this we generate and send a normal
|
|
||||||
* EnterNotify event.
|
|
||||||
*/
|
|
||||||
int root_x, root_y, win_x, win_y;
|
|
||||||
Window root_win, child_win;
|
|
||||||
unsigned int mask;
|
|
||||||
XQueryPointer(x11.display, DefaultRootWindow(x11.display), &root_win,
|
|
||||||
&child_win, &root_x, &root_y, &win_x, &win_y, &mask);
|
|
||||||
|
|
||||||
int target_x, target_y;
|
|
||||||
Window target_root;
|
|
||||||
XTranslateCoordinates(x11.display, DefaultRootWindow(x11.display),
|
|
||||||
child_win, root_x, root_y, &target_x, &target_y, &target_root);
|
|
||||||
|
|
||||||
XEvent event;
|
|
||||||
memset(&event, 0, sizeof(event));
|
|
||||||
event.type = EnterNotify;
|
|
||||||
event.xcrossing.serial = 0;
|
|
||||||
event.xcrossing.send_event = True;
|
|
||||||
event.xcrossing.display = x11.display;
|
|
||||||
event.xcrossing.window = child_win;
|
|
||||||
event.xcrossing.root = root_win;
|
|
||||||
event.xcrossing.subwindow = child_win;
|
|
||||||
event.xcrossing.time = CurrentTime;
|
|
||||||
event.xcrossing.mode = NotifyNormal;
|
|
||||||
event.xcrossing.detail = NotifyNonlinear;
|
|
||||||
event.xcrossing.same_screen = True;
|
|
||||||
event.xcrossing.focus = False;
|
|
||||||
event.xcrossing.x = target_x;
|
|
||||||
event.xcrossing.y = target_y;
|
|
||||||
event.xcrossing.x_root = root_x;
|
|
||||||
event.xcrossing.y_root = root_y;
|
|
||||||
|
|
||||||
XSendEvent(x11.display, child_win, True, EnterWindowMask, &event);
|
|
||||||
XFlush(x11.display);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ static bool cursorTexInit(struct CursorTex * t,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!egl_shaderCompile(t->shader,
|
if (!egl_shaderCompile(t->shader,
|
||||||
vertex_code, vertex_size, fragment_code, fragment_size, false))
|
vertex_code, vertex_size, fragment_code, fragment_size))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to compile the cursor shader");
|
DEBUG_ERROR("Failed to compile the cursor shader");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -76,8 +76,7 @@ bool egl_damageInit(EGL_Damage ** damage)
|
|||||||
|
|
||||||
if (!egl_shaderCompile((*damage)->shader,
|
if (!egl_shaderCompile((*damage)->shader,
|
||||||
b_shader_damage_vert, b_shader_damage_vert_size,
|
b_shader_damage_vert, b_shader_damage_vert_size,
|
||||||
b_shader_damage_frag, b_shader_damage_frag_size,
|
b_shader_damage_frag, b_shader_damage_frag_size))
|
||||||
false))
|
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to compile the damage shader");
|
DEBUG_ERROR("Failed to compile the damage shader");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ struct DesktopShader
|
|||||||
EGL_Shader * shader;
|
EGL_Shader * shader;
|
||||||
GLint uTransform;
|
GLint uTransform;
|
||||||
GLint uDesktopSize;
|
GLint uDesktopSize;
|
||||||
GLint uSamplerType;
|
|
||||||
GLint uScaleAlgo;
|
GLint uScaleAlgo;
|
||||||
GLint uNVGain;
|
GLint uNVGain;
|
||||||
GLint uCBMode;
|
GLint uCBMode;
|
||||||
@@ -58,7 +57,7 @@ struct EGL_Desktop
|
|||||||
EGLDisplay * display;
|
EGLDisplay * display;
|
||||||
|
|
||||||
EGL_Texture * texture;
|
EGL_Texture * texture;
|
||||||
struct DesktopShader dmaShader, shader;
|
struct DesktopShader shader;
|
||||||
EGL_DesktopRects * mesh;
|
EGL_DesktopRects * mesh;
|
||||||
CountedBuffer * matrix;
|
CountedBuffer * matrix;
|
||||||
|
|
||||||
@@ -93,8 +92,7 @@ void toggleNV(int key, void * opaque);
|
|||||||
static bool egl_initDesktopShader(
|
static bool egl_initDesktopShader(
|
||||||
struct DesktopShader * shader,
|
struct DesktopShader * shader,
|
||||||
const char * vertex_code , size_t vertex_size,
|
const char * vertex_code , size_t vertex_size,
|
||||||
const char * fragment_code, size_t fragment_size,
|
const char * fragment_code, size_t fragment_size
|
||||||
bool useDMA
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (!egl_shaderInit(&shader->shader))
|
if (!egl_shaderInit(&shader->shader))
|
||||||
@@ -102,8 +100,7 @@ static bool egl_initDesktopShader(
|
|||||||
|
|
||||||
if (!egl_shaderCompile(shader->shader,
|
if (!egl_shaderCompile(shader->shader,
|
||||||
vertex_code , vertex_size,
|
vertex_code , vertex_size,
|
||||||
fragment_code, fragment_size,
|
fragment_code, fragment_size))
|
||||||
useDMA))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -138,6 +135,15 @@ bool egl_desktopInit(EGL * egl, EGL_Desktop ** desktop_, EGLDisplay * display,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!egl_initDesktopShader(
|
||||||
|
&desktop->shader,
|
||||||
|
b_shader_desktop_vert , b_shader_desktop_vert_size,
|
||||||
|
b_shader_desktop_rgb_frag, b_shader_desktop_rgb_frag_size))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to initialize the generic desktop shader");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!egl_desktopRectsInit(&desktop->mesh, maxRects))
|
if (!egl_desktopRectsInit(&desktop->mesh, maxRects))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to initialize the desktop mesh");
|
DEBUG_ERROR("Failed to initialize the desktop mesh");
|
||||||
@@ -151,27 +157,6 @@ bool egl_desktopInit(EGL * egl, EGL_Desktop ** desktop_, EGLDisplay * display,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!egl_initDesktopShader(
|
|
||||||
&desktop->shader,
|
|
||||||
b_shader_desktop_vert , b_shader_desktop_vert_size,
|
|
||||||
b_shader_desktop_rgb_frag, b_shader_desktop_rgb_frag_size,
|
|
||||||
false))
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to initialize the desktop shader");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (useDMA)
|
|
||||||
if (!egl_initDesktopShader(
|
|
||||||
&desktop->dmaShader,
|
|
||||||
b_shader_desktop_vert , b_shader_desktop_vert_size,
|
|
||||||
b_shader_desktop_rgb_frag, b_shader_desktop_rgb_frag_size,
|
|
||||||
true))
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to initialize the desktop DMA shader");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
app_registerKeybind(0, 'N', toggleNV, desktop,
|
app_registerKeybind(0, 'N', toggleNV, desktop,
|
||||||
"Toggle night vision mode");
|
"Toggle night vision mode");
|
||||||
|
|
||||||
@@ -220,12 +205,11 @@ void egl_desktopFree(EGL_Desktop ** desktop)
|
|||||||
if (!*desktop)
|
if (!*desktop)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
egl_textureFree (&(*desktop)->texture );
|
egl_textureFree (&(*desktop)->texture );
|
||||||
egl_textureFree (&(*desktop)->spiceTexture );
|
egl_textureFree (&(*desktop)->spiceTexture );
|
||||||
egl_shaderFree (&(*desktop)->shader .shader);
|
egl_shaderFree (&(*desktop)->shader.shader);
|
||||||
egl_shaderFree (&(*desktop)->dmaShader.shader);
|
egl_desktopRectsFree(&(*desktop)->mesh );
|
||||||
egl_desktopRectsFree(&(*desktop)->mesh );
|
countedBufferRelease(&(*desktop)->matrix );
|
||||||
countedBufferRelease(&(*desktop)->matrix );
|
|
||||||
|
|
||||||
egl_postProcessFree(&(*desktop)->pp);
|
egl_postProcessFree(&(*desktop)->pp);
|
||||||
|
|
||||||
@@ -415,17 +399,18 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
|||||||
if (atomic_exchange(&desktop->processFrame, false) ||
|
if (atomic_exchange(&desktop->processFrame, false) ||
|
||||||
egl_postProcessConfigModified(desktop->pp))
|
egl_postProcessConfigModified(desktop->pp))
|
||||||
egl_postProcessRun(desktop->pp, tex, desktop->mesh,
|
egl_postProcessRun(desktop->pp, tex, desktop->mesh,
|
||||||
width, height, outputWidth, outputHeight, desktop->useDMA);
|
width, height, outputWidth, outputHeight);
|
||||||
|
|
||||||
unsigned int finalSizeX, finalSizeY;
|
unsigned int finalSizeX, finalSizeY;
|
||||||
EGL_Texture * texture = egl_postProcessGetOutput(desktop->pp,
|
GLuint texture = egl_postProcessGetOutput(desktop->pp,
|
||||||
&finalSizeX, &finalSizeY);
|
&finalSizeX, &finalSizeY);
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
egl_resetViewport(desktop->egl);
|
egl_resetViewport(desktop->egl);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
egl_textureBind(texture);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
glBindSampler(0, tex->sampler);
|
||||||
|
|
||||||
if (finalSizeX > width || finalSizeY > height)
|
if (finalSizeX > width || finalSizeY > height)
|
||||||
scaleType = EGL_DESKTOP_DOWNSCALE;
|
scaleType = EGL_DESKTOP_DOWNSCALE;
|
||||||
@@ -450,10 +435,7 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
|||||||
scaleAlgo = desktop->scaleAlgo;
|
scaleAlgo = desktop->scaleAlgo;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct DesktopShader * shader =
|
const struct DesktopShader * shader = &desktop->shader;
|
||||||
desktop->useDMA && texture == desktop->texture ?
|
|
||||||
&desktop->dmaShader : &desktop->shader;
|
|
||||||
|
|
||||||
EGL_Uniform uniforms[] =
|
EGL_Uniform uniforms[] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -68,11 +68,9 @@ typedef struct EGL_FilterOps
|
|||||||
/* reads filter state from options */
|
/* reads filter state from options */
|
||||||
void (*loadState)(EGL_Filter * filter);
|
void (*loadState)(EGL_Filter * filter);
|
||||||
|
|
||||||
/* set the input format of the filter
|
/* set the input format of the filter */
|
||||||
* useDMA will be true if the texture provided needs to use samplerExternalOES
|
|
||||||
*/
|
|
||||||
bool (*setup)(EGL_Filter * filter, enum EGL_PixelFormat pixFmt,
|
bool (*setup)(EGL_Filter * filter, enum EGL_PixelFormat pixFmt,
|
||||||
unsigned int width, unsigned int height, bool useDMA);
|
unsigned int width, unsigned int height);
|
||||||
|
|
||||||
/* set the output resolution hint for the filter
|
/* set the output resolution hint for the filter
|
||||||
* this is optional and only a hint */
|
* this is optional and only a hint */
|
||||||
@@ -89,8 +87,8 @@ typedef struct EGL_FilterOps
|
|||||||
|
|
||||||
/* runs the filter on the provided texture
|
/* runs the filter on the provided texture
|
||||||
* returns the processed texture as the output */
|
* returns the processed texture as the output */
|
||||||
EGL_Texture * (*run)(EGL_Filter * filter, EGL_FilterRects * rects,
|
GLuint (*run)(EGL_Filter * filter, EGL_FilterRects * rects,
|
||||||
EGL_Texture * texture);
|
GLuint texture);
|
||||||
|
|
||||||
/* called when the filter output is no loger needed so it can release memory
|
/* called when the filter output is no loger needed so it can release memory
|
||||||
* this is optional */
|
* this is optional */
|
||||||
@@ -135,10 +133,9 @@ static inline void egl_filterLoadState(EGL_Filter * filter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline bool egl_filterSetup(EGL_Filter * filter,
|
static inline bool egl_filterSetup(EGL_Filter * filter,
|
||||||
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height,
|
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height)
|
||||||
bool useDMA)
|
|
||||||
{
|
{
|
||||||
return filter->ops.setup(filter, pixFmt, width, height, useDMA);
|
return filter->ops.setup(filter, pixFmt, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void egl_filterSetOutputResHint(EGL_Filter * filter,
|
static inline void egl_filterSetOutputResHint(EGL_Filter * filter,
|
||||||
@@ -159,8 +156,8 @@ static inline bool egl_filterPrepare(EGL_Filter * filter)
|
|||||||
return filter->ops.prepare(filter);
|
return filter->ops.prepare(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline EGL_Texture * egl_filterRun(EGL_Filter * filter,
|
static inline GLuint egl_filterRun(EGL_Filter * filter,
|
||||||
EGL_FilterRects * rects, EGL_Texture * texture)
|
EGL_FilterRects * rects, GLuint texture)
|
||||||
{
|
{
|
||||||
return filter->ops.run(filter, rects, texture);
|
return filter->ops.run(filter, rects, texture);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ typedef struct EGL_FilterDownscale
|
|||||||
EGL_Shader * lanczos2;
|
EGL_Shader * lanczos2;
|
||||||
|
|
||||||
DownscaleFilter filter;
|
DownscaleFilter filter;
|
||||||
int useDMA;
|
|
||||||
enum EGL_PixelFormat pixFmt;
|
enum EGL_PixelFormat pixFmt;
|
||||||
unsigned int width, height;
|
unsigned int width, height;
|
||||||
float pixelSize;
|
float pixelSize;
|
||||||
@@ -158,26 +157,55 @@ static bool egl_filterDownscaleInit(EGL_Filter ** filter)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->useDMA = -1;
|
|
||||||
|
|
||||||
if (!egl_shaderInit(&this->nearest))
|
if (!egl_shaderInit(&this->nearest))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to initialize the shader");
|
DEBUG_ERROR("Failed to initialize the shader");
|
||||||
goto error_this;
|
goto error_this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!egl_shaderCompile(this->nearest,
|
||||||
|
b_shader_basic_vert , b_shader_basic_vert_size,
|
||||||
|
b_shader_downscale_frag, b_shader_downscale_frag_size)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to compile the shader");
|
||||||
|
goto error_shader;
|
||||||
|
}
|
||||||
|
|
||||||
if (!egl_shaderInit(&this->linear))
|
if (!egl_shaderInit(&this->linear))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to initialize the shader");
|
DEBUG_ERROR("Failed to initialize the shader");
|
||||||
goto error_this;
|
goto error_this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!egl_shaderCompile(this->linear,
|
||||||
|
b_shader_basic_vert, b_shader_basic_vert_size,
|
||||||
|
b_shader_downscale_linear_frag, b_shader_downscale_linear_frag_size)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to compile the shader");
|
||||||
|
goto error_shader;
|
||||||
|
}
|
||||||
|
|
||||||
if (!egl_shaderInit(&this->lanczos2))
|
if (!egl_shaderInit(&this->lanczos2))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to initialize the shader");
|
DEBUG_ERROR("Failed to initialize the shader");
|
||||||
goto error_this;
|
goto error_this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!egl_shaderCompile(this->lanczos2,
|
||||||
|
b_shader_basic_vert, b_shader_basic_vert_size,
|
||||||
|
b_shader_downscale_lanczos2_frag, b_shader_downscale_lanczos2_frag_size)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to compile the shader");
|
||||||
|
goto error_shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->uNearest.type = EGL_UNIFORM_TYPE_3F;
|
||||||
|
this->uNearest.location =
|
||||||
|
egl_shaderGetUniform(this->nearest, "uConfig");
|
||||||
|
|
||||||
if (!egl_framebufferInit(&this->fb))
|
if (!egl_framebufferInit(&this->fb))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to initialize the framebuffer");
|
DEBUG_ERROR("Failed to initialize the framebuffer");
|
||||||
@@ -298,8 +326,7 @@ static bool egl_filterDownscaleImguiConfig(EGL_Filter * filter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool egl_filterDownscaleSetup(EGL_Filter * filter,
|
static bool egl_filterDownscaleSetup(EGL_Filter * filter,
|
||||||
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height,
|
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height)
|
||||||
bool useDMA)
|
|
||||||
{
|
{
|
||||||
EGL_FilterDownscale * this = UPCAST(EGL_FilterDownscale, filter);
|
EGL_FilterDownscale * this = UPCAST(EGL_FilterDownscale, filter);
|
||||||
|
|
||||||
@@ -309,48 +336,6 @@ static bool egl_filterDownscaleSetup(EGL_Filter * filter,
|
|||||||
if (!this->enable)
|
if (!this->enable)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (this->useDMA != useDMA)
|
|
||||||
{
|
|
||||||
if (!egl_shaderCompile(this->nearest,
|
|
||||||
b_shader_basic_vert , b_shader_basic_vert_size,
|
|
||||||
b_shader_downscale_frag,
|
|
||||||
b_shader_downscale_frag_size,
|
|
||||||
useDMA)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to compile the shader");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!egl_shaderCompile(this->linear,
|
|
||||||
b_shader_basic_vert, b_shader_basic_vert_size,
|
|
||||||
b_shader_downscale_linear_frag,
|
|
||||||
b_shader_downscale_linear_frag_size,
|
|
||||||
useDMA)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to compile the shader");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!egl_shaderCompile(this->lanczos2,
|
|
||||||
b_shader_basic_vert, b_shader_basic_vert_size,
|
|
||||||
b_shader_downscale_lanczos2_frag,
|
|
||||||
b_shader_downscale_lanczos2_frag_size,
|
|
||||||
useDMA)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to compile the shader");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->uNearest.type = EGL_UNIFORM_TYPE_3F;
|
|
||||||
this->uNearest.location =
|
|
||||||
egl_shaderGetUniform(this->nearest, "uConfig");
|
|
||||||
|
|
||||||
this->useDMA = useDMA;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->prepared &&
|
if (this->prepared &&
|
||||||
pixFmt == this->pixFmt &&
|
pixFmt == this->pixFmt &&
|
||||||
this->width == width &&
|
this->width == width &&
|
||||||
@@ -400,15 +385,15 @@ static bool egl_filterDownscalePrepare(EGL_Filter * filter)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static EGL_Texture * egl_filterDownscaleRun(EGL_Filter * filter,
|
static GLuint egl_filterDownscaleRun(EGL_Filter * filter,
|
||||||
EGL_FilterRects * rects, EGL_Texture * texture)
|
EGL_FilterRects * rects, GLuint texture)
|
||||||
{
|
{
|
||||||
EGL_FilterDownscale * this = UPCAST(EGL_FilterDownscale, filter);
|
EGL_FilterDownscale * this = UPCAST(EGL_FilterDownscale, filter);
|
||||||
|
|
||||||
egl_framebufferBind(this->fb);
|
egl_framebufferBind(this->fb);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
egl_textureBind(texture);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
|
||||||
EGL_Shader * shader;
|
EGL_Shader * shader;
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ typedef struct EGL_FilterFFXCAS
|
|||||||
EGL_Shader * shader;
|
EGL_Shader * shader;
|
||||||
bool enable;
|
bool enable;
|
||||||
|
|
||||||
int useDMA;
|
|
||||||
enum EGL_PixelFormat pixFmt;
|
enum EGL_PixelFormat pixFmt;
|
||||||
unsigned int width, height;
|
unsigned int width, height;
|
||||||
float sharpness;
|
float sharpness;
|
||||||
@@ -107,14 +106,21 @@ static bool egl_filterFFXCASInit(EGL_Filter ** filter)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->useDMA = -1;
|
|
||||||
|
|
||||||
if (!egl_shaderInit(&this->shader))
|
if (!egl_shaderInit(&this->shader))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to initialize the shader");
|
DEBUG_ERROR("Failed to initialize the shader");
|
||||||
goto error_this;
|
goto error_this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!egl_shaderCompile(this->shader,
|
||||||
|
b_shader_basic_vert , b_shader_basic_vert_size,
|
||||||
|
b_shader_ffx_cas_frag, b_shader_ffx_cas_frag_size)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to compile the shader");
|
||||||
|
goto error_shader;
|
||||||
|
}
|
||||||
|
|
||||||
this->consts = countedBufferNew(8 * sizeof(GLuint));
|
this->consts = countedBufferNew(8 * sizeof(GLuint));
|
||||||
if (!this->consts)
|
if (!this->consts)
|
||||||
{
|
{
|
||||||
@@ -122,6 +128,12 @@ static bool egl_filterFFXCASInit(EGL_Filter ** filter)
|
|||||||
goto error_shader;
|
goto error_shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
egl_shaderSetUniforms(this->shader, &(EGL_Uniform) {
|
||||||
|
.type = EGL_UNIFORM_TYPE_4UIV,
|
||||||
|
.location = egl_shaderGetUniform(this->shader, "uConsts"),
|
||||||
|
.v = this->consts,
|
||||||
|
}, 1);
|
||||||
|
|
||||||
egl_filterFFXCASLoadState(&this->base);
|
egl_filterFFXCASLoadState(&this->base);
|
||||||
|
|
||||||
if (!egl_framebufferInit(&this->fb))
|
if (!egl_framebufferInit(&this->fb))
|
||||||
@@ -208,35 +220,13 @@ static bool egl_filterFFXCASImguiConfig(EGL_Filter * filter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool egl_filterFFXCASSetup(EGL_Filter * filter,
|
static bool egl_filterFFXCASSetup(EGL_Filter * filter,
|
||||||
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height,
|
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height)
|
||||||
bool useDMA)
|
|
||||||
{
|
{
|
||||||
EGL_FilterFFXCAS * this = UPCAST(EGL_FilterFFXCAS, filter);
|
EGL_FilterFFXCAS * this = UPCAST(EGL_FilterFFXCAS, filter);
|
||||||
|
|
||||||
if (!this->enable)
|
if (!this->enable)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (this->useDMA != useDMA)
|
|
||||||
{
|
|
||||||
if (!egl_shaderCompile(this->shader,
|
|
||||||
b_shader_basic_vert , b_shader_basic_vert_size,
|
|
||||||
b_shader_ffx_cas_frag, b_shader_ffx_cas_frag_size,
|
|
||||||
useDMA)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to compile the shader");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
egl_shaderSetUniforms(this->shader, &(EGL_Uniform) {
|
|
||||||
.type = EGL_UNIFORM_TYPE_4UIV,
|
|
||||||
.location = egl_shaderGetUniform(this->shader, "uConsts"),
|
|
||||||
.v = this->consts,
|
|
||||||
}, 1);
|
|
||||||
|
|
||||||
this->useDMA = useDMA;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pixFmt == this->pixFmt && this->width == width && this->height == height)
|
if (pixFmt == this->pixFmt && this->width == width && this->height == height)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -272,15 +262,15 @@ static bool egl_filterFFXCASPrepare(EGL_Filter * filter)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static EGL_Texture * egl_filterFFXCASRun(EGL_Filter * filter,
|
static GLuint egl_filterFFXCASRun(EGL_Filter * filter,
|
||||||
EGL_FilterRects * rects, EGL_Texture * texture)
|
EGL_FilterRects * rects, GLuint texture)
|
||||||
{
|
{
|
||||||
EGL_FilterFFXCAS * this = UPCAST(EGL_FilterFFXCAS, filter);
|
EGL_FilterFFXCAS * this = UPCAST(EGL_FilterFFXCAS, filter);
|
||||||
|
|
||||||
egl_framebufferBind(this->fb);
|
egl_framebufferBind(this->fb);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
egl_textureBind(texture);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
glBindSampler(0, this->sampler);
|
glBindSampler(0, this->sampler);
|
||||||
|
|
||||||
egl_shaderUse(this->shader);
|
egl_shaderUse(this->shader);
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ typedef struct EGL_FilterFFXFSR1
|
|||||||
CountedBuffer * consts;
|
CountedBuffer * consts;
|
||||||
EGL_Uniform easuUniform[2], rcasUniform;
|
EGL_Uniform easuUniform[2], rcasUniform;
|
||||||
|
|
||||||
int useDMA;
|
|
||||||
enum EGL_PixelFormat pixFmt;
|
enum EGL_PixelFormat pixFmt;
|
||||||
unsigned int width, height;
|
unsigned int width, height;
|
||||||
unsigned int inWidth, inHeight;
|
unsigned int inWidth, inHeight;
|
||||||
@@ -110,8 +109,6 @@ static bool egl_filterFFXFSR1Init(EGL_Filter ** filter)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->useDMA = -1;
|
|
||||||
|
|
||||||
if (!egl_shaderInit(&this->easu))
|
if (!egl_shaderInit(&this->easu))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to initialize the Easu shader");
|
DEBUG_ERROR("Failed to initialize the Easu shader");
|
||||||
@@ -124,10 +121,18 @@ static bool egl_filterFFXFSR1Init(EGL_Filter ** filter)
|
|||||||
goto error_esau;
|
goto error_esau;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!egl_shaderCompile(this->easu,
|
||||||
|
b_shader_basic_vert , b_shader_basic_vert_size,
|
||||||
|
b_shader_ffx_fsr1_easu_frag, b_shader_ffx_fsr1_easu_frag_size)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to compile the Easu shader");
|
||||||
|
goto error_rcas;
|
||||||
|
}
|
||||||
|
|
||||||
if (!egl_shaderCompile(this->rcas,
|
if (!egl_shaderCompile(this->rcas,
|
||||||
b_shader_basic_vert , b_shader_basic_vert_size,
|
b_shader_basic_vert , b_shader_basic_vert_size,
|
||||||
b_shader_ffx_fsr1_rcas_frag, b_shader_ffx_fsr1_rcas_frag_size,
|
b_shader_ffx_fsr1_rcas_frag, b_shader_ffx_fsr1_rcas_frag_size)
|
||||||
false)
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to compile the Rcas shader");
|
DEBUG_ERROR("Failed to compile the Rcas shader");
|
||||||
@@ -143,6 +148,14 @@ static bool egl_filterFFXFSR1Init(EGL_Filter ** filter)
|
|||||||
|
|
||||||
egl_filterFFXFSR1LoadState(&this->base);
|
egl_filterFFXFSR1LoadState(&this->base);
|
||||||
|
|
||||||
|
this->easuUniform[0].type = EGL_UNIFORM_TYPE_4UIV;
|
||||||
|
this->easuUniform[0].location =
|
||||||
|
egl_shaderGetUniform(this->easu, "uConsts");
|
||||||
|
this->easuUniform[0].v = this->consts;
|
||||||
|
this->easuUniform[1].type = EGL_UNIFORM_TYPE_2F;
|
||||||
|
this->easuUniform[1].location =
|
||||||
|
egl_shaderGetUniform(this->easu, "uOutRes");
|
||||||
|
|
||||||
this->rcasUniform.type = EGL_UNIFORM_TYPE_4UI;
|
this->rcasUniform.type = EGL_UNIFORM_TYPE_4UI;
|
||||||
this->rcasUniform.location = egl_shaderGetUniform(this->rcas, "uConsts");
|
this->rcasUniform.location = egl_shaderGetUniform(this->rcas, "uConsts");
|
||||||
rcasUpdateUniform(this);
|
rcasUpdateUniform(this);
|
||||||
@@ -322,37 +335,13 @@ static void egl_filterFFXFSR1SetOutputResHint(EGL_Filter * filter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool egl_filterFFXFSR1Setup(EGL_Filter * filter,
|
static bool egl_filterFFXFSR1Setup(EGL_Filter * filter,
|
||||||
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height,
|
enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height)
|
||||||
bool useDMA)
|
|
||||||
{
|
{
|
||||||
EGL_FilterFFXFSR1 * this = UPCAST(EGL_FilterFFXFSR1, filter);
|
EGL_FilterFFXFSR1 * this = UPCAST(EGL_FilterFFXFSR1, filter);
|
||||||
|
|
||||||
if (!this->enable)
|
if (!this->enable)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (this->useDMA != useDMA)
|
|
||||||
{
|
|
||||||
if (!egl_shaderCompile(this->easu,
|
|
||||||
b_shader_basic_vert , b_shader_basic_vert_size,
|
|
||||||
b_shader_ffx_fsr1_easu_frag, b_shader_ffx_fsr1_easu_frag_size,
|
|
||||||
useDMA)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Failed to compile the Easu shader");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->easuUniform[0].type = EGL_UNIFORM_TYPE_4UIV;
|
|
||||||
this->easuUniform[0].location =
|
|
||||||
egl_shaderGetUniform(this->easu, "uConsts");
|
|
||||||
this->easuUniform[0].v = this->consts;
|
|
||||||
this->easuUniform[1].type = EGL_UNIFORM_TYPE_2F;
|
|
||||||
this->easuUniform[1].location =
|
|
||||||
egl_shaderGetUniform(this->easu, "uOutRes");
|
|
||||||
|
|
||||||
this->useDMA = useDMA;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->active = this->width > width && this->height > height;
|
this->active = this->width > width && this->height > height;
|
||||||
if (!this->active)
|
if (!this->active)
|
||||||
return false;
|
return false;
|
||||||
@@ -406,15 +395,15 @@ static bool egl_filterFFXFSR1Prepare(EGL_Filter * filter)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static EGL_Texture * egl_filterFFXFSR1Run(EGL_Filter * filter,
|
static GLuint egl_filterFFXFSR1Run(EGL_Filter * filter,
|
||||||
EGL_FilterRects * rects, EGL_Texture * texture)
|
EGL_FilterRects * rects, GLuint texture)
|
||||||
{
|
{
|
||||||
EGL_FilterFFXFSR1 * this = UPCAST(EGL_FilterFFXFSR1, filter);
|
EGL_FilterFFXFSR1 * this = UPCAST(EGL_FilterFFXFSR1, filter);
|
||||||
|
|
||||||
// pass 1, Easu
|
// pass 1, Easu
|
||||||
egl_framebufferBind(this->easuFb);
|
egl_framebufferBind(this->easuFb);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
egl_textureBind(texture);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
glBindSampler(0, this->sampler);
|
glBindSampler(0, this->sampler);
|
||||||
egl_shaderUse(this->easu);
|
egl_shaderUse(this->easu);
|
||||||
egl_filterRectsRender(this->easu, rects);
|
egl_filterRectsRender(this->easu, rects);
|
||||||
@@ -423,7 +412,7 @@ static EGL_Texture * egl_filterFFXFSR1Run(EGL_Filter * filter,
|
|||||||
// pass 2, Rcas
|
// pass 2, Rcas
|
||||||
egl_framebufferBind(this->rcasFb);
|
egl_framebufferBind(this->rcasFb);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
egl_textureBind(texture);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
glBindSampler(0, this->sampler);
|
glBindSampler(0, this->sampler);
|
||||||
egl_shaderUse(this->rcas);
|
egl_shaderUse(this->rcas);
|
||||||
egl_filterRectsRender(this->rcas, rects);
|
egl_filterRectsRender(this->rcas, rects);
|
||||||
|
|||||||
@@ -100,7 +100,9 @@ void egl_framebufferBind(EGL_Framebuffer * this)
|
|||||||
glViewport(0, 0, this->tex->format.width, this->tex->format.height);
|
glViewport(0, 0, this->tex->format.width, this->tex->format.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
EGL_Texture * egl_framebufferGetTexture(EGL_Framebuffer * this)
|
GLuint egl_framebufferGetTexture(EGL_Framebuffer * this)
|
||||||
{
|
{
|
||||||
return this->tex;
|
GLuint output;
|
||||||
|
egl_textureGet(this->tex, &output, NULL, NULL);
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,4 +32,4 @@ bool egl_framebufferSetup(EGL_Framebuffer * this, enum EGL_PixelFormat pixFmt,
|
|||||||
|
|
||||||
void egl_framebufferBind(EGL_Framebuffer * this);
|
void egl_framebufferBind(EGL_Framebuffer * this);
|
||||||
|
|
||||||
EGL_Texture * egl_framebufferGetTexture(EGL_Framebuffer * this);
|
GLuint egl_framebufferGetTexture(EGL_Framebuffer * this);
|
||||||
|
|||||||
@@ -10,4 +10,4 @@ function process(line, second) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{ process($0, $2) } END { print "\0"; }
|
{ process($0, $2) }
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ static const EGL_FilterOps * EGL_Filters[] =
|
|||||||
struct EGL_PostProcess
|
struct EGL_PostProcess
|
||||||
{
|
{
|
||||||
Vector filters;
|
Vector filters;
|
||||||
EGL_Texture * output;
|
GLuint output;
|
||||||
unsigned int outputX, outputY;
|
unsigned int outputX, outputY;
|
||||||
_Atomic(bool) modified;
|
_Atomic(bool) modified;
|
||||||
|
|
||||||
@@ -606,7 +606,7 @@ bool egl_postProcessConfigModified(EGL_PostProcess * this)
|
|||||||
|
|
||||||
bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
||||||
EGL_DesktopRects * rects, int desktopWidth, int desktopHeight,
|
EGL_DesktopRects * rects, int desktopWidth, int desktopHeight,
|
||||||
unsigned int targetX, unsigned int targetY, bool useDMA)
|
unsigned int targetX, unsigned int targetY)
|
||||||
{
|
{
|
||||||
if (targetX == 0 && targetY == 0)
|
if (targetX == 0 && targetY == 0)
|
||||||
DEBUG_FATAL("targetX || targetY == 0");
|
DEBUG_FATAL("targetX || targetY == 0");
|
||||||
@@ -614,9 +614,8 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
|||||||
EGL_Filter * lastFilter = NULL;
|
EGL_Filter * lastFilter = NULL;
|
||||||
unsigned int sizeX, sizeY;
|
unsigned int sizeX, sizeY;
|
||||||
|
|
||||||
//TODO: clean this up
|
GLuint texture;
|
||||||
GLuint _unused;
|
if (egl_textureGet(tex, &texture, &sizeX, &sizeY) != EGL_TEX_STATUS_OK)
|
||||||
if (egl_textureGet(tex, &_unused, &sizeX, &sizeY) != EGL_TEX_STATUS_OK)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (atomic_exchange(&this->modified, false))
|
if (atomic_exchange(&this->modified, false))
|
||||||
@@ -637,12 +636,11 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
|||||||
};
|
};
|
||||||
|
|
||||||
EGL_Filter * filter;
|
EGL_Filter * filter;
|
||||||
EGL_Texture * texture = tex;
|
|
||||||
vector_forEach(filter, &this->filters)
|
vector_forEach(filter, &this->filters)
|
||||||
{
|
{
|
||||||
egl_filterSetOutputResHint(filter, targetX, targetY);
|
egl_filterSetOutputResHint(filter, targetX, targetY);
|
||||||
|
|
||||||
if (!egl_filterSetup(filter, tex->format.pixFmt, sizeX, sizeY, useDMA) ||
|
if (!egl_filterSetup(filter, tex->format.pixFmt, sizeX, sizeY) ||
|
||||||
!egl_filterPrepare(filter))
|
!egl_filterPrepare(filter))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -653,9 +651,6 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
|||||||
egl_filterRelease(lastFilter);
|
egl_filterRelease(lastFilter);
|
||||||
|
|
||||||
lastFilter = filter;
|
lastFilter = filter;
|
||||||
|
|
||||||
// the first filter to run will convert to a normal texture
|
|
||||||
useDMA = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->output = texture;
|
this->output = texture;
|
||||||
@@ -664,7 +659,7 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
EGL_Texture * egl_postProcessGetOutput(EGL_PostProcess * this,
|
GLuint egl_postProcessGetOutput(EGL_PostProcess * this,
|
||||||
unsigned int * outputX, unsigned int * outputY)
|
unsigned int * outputX, unsigned int * outputY)
|
||||||
{
|
{
|
||||||
*outputX = this->outputX;
|
*outputX = this->outputX;
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ bool egl_postProcessConfigModified(EGL_PostProcess * this);
|
|||||||
* targetX/Y is the final target output dimension hint if scalers are present */
|
* targetX/Y is the final target output dimension hint if scalers are present */
|
||||||
bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
||||||
EGL_DesktopRects * rects, int desktopWidth, int desktopHeight,
|
EGL_DesktopRects * rects, int desktopWidth, int desktopHeight,
|
||||||
unsigned int targetX, unsigned int targetY, bool useDMA);
|
unsigned int targetX, unsigned int targetY);
|
||||||
|
|
||||||
EGL_Texture * egl_postProcessGetOutput(EGL_PostProcess * this,
|
GLuint egl_postProcessGetOutput(EGL_PostProcess * this,
|
||||||
unsigned int * outputX, unsigned int * outputY);
|
unsigned int * outputX, unsigned int * outputY);
|
||||||
|
|||||||
@@ -64,8 +64,7 @@ void egl_shaderFree(EGL_Shader ** shader)
|
|||||||
*shader = NULL;
|
*shader = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool egl_shaderLoad(EGL_Shader * this,
|
bool egl_shaderLoad(EGL_Shader * this, const char * vertex_file, const char * fragment_file)
|
||||||
const char * vertex_file, const char * fragment_file, bool useDMA)
|
|
||||||
{
|
{
|
||||||
char * vertex_code, * fragment_code;
|
char * vertex_code, * fragment_code;
|
||||||
size_t vertex_size, fragment_size;
|
size_t vertex_size, fragment_size;
|
||||||
@@ -87,16 +86,13 @@ bool egl_shaderLoad(EGL_Shader * this,
|
|||||||
|
|
||||||
DEBUG_INFO("Loaded fragment shader: %s", fragment_file);
|
DEBUG_INFO("Loaded fragment shader: %s", fragment_file);
|
||||||
|
|
||||||
bool ret = egl_shaderCompile(this,
|
bool ret = egl_shaderCompile(this, vertex_code, vertex_size, fragment_code, fragment_size);
|
||||||
vertex_code, vertex_size, fragment_code, fragment_size,
|
|
||||||
useDMA);
|
|
||||||
|
|
||||||
free(vertex_code);
|
free(vertex_code);
|
||||||
free(fragment_code);
|
free(fragment_code);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool shaderCompile(EGL_Shader * this, const char * vertex_code,
|
bool egl_shaderCompile(EGL_Shader * this, const char * vertex_code,
|
||||||
size_t vertex_size, const char * fragment_code, size_t fragment_size)
|
size_t vertex_size, const char * fragment_code, size_t fragment_size)
|
||||||
{
|
{
|
||||||
if (this->hasShader)
|
if (this->hasShader)
|
||||||
@@ -208,64 +204,6 @@ static bool shaderCompile(EGL_Shader * this, const char * vertex_code,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool egl_shaderCompile(EGL_Shader * this, const char * vertex_code,
|
|
||||||
size_t vertex_size, const char * fragment_code, size_t fragment_size,
|
|
||||||
bool useDMA)
|
|
||||||
{
|
|
||||||
if (useDMA)
|
|
||||||
{
|
|
||||||
const char * search = "sampler2D";
|
|
||||||
const char * replace = "samplerExternalOES";
|
|
||||||
|
|
||||||
const char * src = fragment_code;
|
|
||||||
int instances = 0;
|
|
||||||
while((src = strstr(src, search)))
|
|
||||||
{
|
|
||||||
++instances;
|
|
||||||
src += strlen(search);
|
|
||||||
}
|
|
||||||
|
|
||||||
const int diff = (strlen(replace) - strlen(search)) * instances;
|
|
||||||
char * newCode = malloc(fragment_size + diff);
|
|
||||||
if (!newCode)
|
|
||||||
{
|
|
||||||
DEBUG_ERROR("Out of memory");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
src = fragment_code;
|
|
||||||
char * dst = newCode;
|
|
||||||
for(int i = 0; i < instances; ++i)
|
|
||||||
{
|
|
||||||
const char * pos = strstr(src, search);
|
|
||||||
const int offset = pos - src;
|
|
||||||
|
|
||||||
memcpy(dst, src, offset);
|
|
||||||
dst += offset;
|
|
||||||
src = pos + strlen(search);
|
|
||||||
|
|
||||||
memcpy(dst, replace, strlen(replace));
|
|
||||||
dst += strlen(replace);
|
|
||||||
}
|
|
||||||
|
|
||||||
const int final = fragment_size - (src - fragment_code);
|
|
||||||
memcpy(dst, src, final);
|
|
||||||
dst[final] = 0;
|
|
||||||
|
|
||||||
bool result = shaderCompile(
|
|
||||||
this,
|
|
||||||
vertex_code, vertex_size,
|
|
||||||
newCode , fragment_size + diff);
|
|
||||||
|
|
||||||
free(newCode);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return shaderCompile(this,
|
|
||||||
vertex_code , vertex_size,
|
|
||||||
fragment_code, fragment_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void egl_shaderSetUniforms(EGL_Shader * this, EGL_Uniform * uniforms, int count)
|
void egl_shaderSetUniforms(EGL_Shader * this, EGL_Uniform * uniforms, int count)
|
||||||
{
|
{
|
||||||
egl_shaderFreeUniforms(this);
|
egl_shaderFreeUniforms(this);
|
||||||
|
|||||||
@@ -97,11 +97,10 @@ bool egl_shaderInit(EGL_Shader ** shader);
|
|||||||
void egl_shaderFree(EGL_Shader ** shader);
|
void egl_shaderFree(EGL_Shader ** shader);
|
||||||
|
|
||||||
bool egl_shaderLoad(EGL_Shader * model, const char * vertex_file,
|
bool egl_shaderLoad(EGL_Shader * model, const char * vertex_file,
|
||||||
const char * fragment_file, bool useDMA);
|
const char * fragment_file);
|
||||||
|
|
||||||
bool egl_shaderCompile(EGL_Shader * model, const char * vertex_code,
|
bool egl_shaderCompile(EGL_Shader * model, const char * vertex_code,
|
||||||
size_t vertex_size, const char * fragment_code, size_t fragment_size,
|
size_t vertex_size, const char * fragment_code, size_t fragment_size);
|
||||||
bool useDMA);
|
|
||||||
|
|
||||||
void egl_shaderSetUniforms(EGL_Shader * shader, EGL_Uniform * uniforms,
|
void egl_shaderSetUniforms(EGL_Shader * shader, EGL_Uniform * uniforms,
|
||||||
int count);
|
int count);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
precision highp float;
|
precision mediump float;
|
||||||
|
|
||||||
layout(location = 0) in vec2 vertex;
|
layout(location = 0) in vec2 vertex;
|
||||||
out vec2 fragCoord;
|
out vec2 fragCoord;
|
||||||
|
|||||||
@@ -1,21 +1,16 @@
|
|||||||
#if __VERSION__ == 300
|
#if __VERSION__ == 300
|
||||||
vec4 textureGather(sampler2D tex, vec2 uv, int comp)
|
vec4 textureGather(sampler2D tex, vec2 uv, int comp)
|
||||||
{
|
{
|
||||||
vec2 res = vec2(textureSize(tex, 0));
|
vec4 c0 = textureOffset(tex, uv, ivec2(0,1));
|
||||||
ivec2 p = ivec2((uv * res) - 0.5f);
|
vec4 c1 = textureOffset(tex, uv, ivec2(1,1));
|
||||||
|
vec4 c2 = textureOffset(tex, uv, ivec2(1,0));
|
||||||
// NOTE: we can't use texelFecthOffset because sampler2D may actually be samplerExternalOES
|
vec4 c3 = textureOffset(tex, uv, ivec2(0,0));
|
||||||
vec4 c0 = texelFetch(tex, p+ivec2(0,1), 0);
|
|
||||||
vec4 c1 = texelFetch(tex, p+ivec2(1,1), 0);
|
|
||||||
vec4 c2 = texelFetch(tex, p+ivec2(1,0), 0);
|
|
||||||
vec4 c3 = texelFetch(tex, p+ivec2(0,0), 0);
|
|
||||||
|
|
||||||
return vec4(c0[comp], c1[comp], c2[comp],c3[comp]);
|
return vec4(c0[comp], c1[comp], c2[comp],c3[comp]);
|
||||||
}
|
}
|
||||||
#elif __VERSION__ < 300
|
#elif __VERSION__ < 300
|
||||||
vec4 textureGather(sampler2D tex, vec2 uv, int comp)
|
vec4 textureGather(sampler2D tex, vec2 uv, int comp)
|
||||||
{
|
{
|
||||||
vec4 c3 = texture(tex, uv);
|
vec4 c3 = texture2D(tex, uv);
|
||||||
return vec4(c3[comp], c3[comp], c3[comp],c3[comp]);
|
return vec4(c3[comp], c3[comp], c3[comp],c3[comp]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
precision highp float;
|
precision mediump float;
|
||||||
|
|
||||||
layout(location = 0) in vec3 vertexPosition_modelspace;
|
layout(location = 0) in vec3 vertexPosition_modelspace;
|
||||||
layout(location = 1) in vec2 vertexUV;
|
layout(location = 1) in vec2 vertexUV;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
precision highp float;
|
precision mediump float;
|
||||||
|
|
||||||
in vec2 uv;
|
in vec2 uv;
|
||||||
out vec4 color;
|
out vec4 color;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
precision highp float;
|
precision mediump float;
|
||||||
|
|
||||||
#include "color_blind.h"
|
#include "color_blind.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
precision highp float;
|
precision mediump float;
|
||||||
|
|
||||||
out vec4 color;
|
out vec4 color;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
precision highp float;
|
precision mediump float;
|
||||||
|
|
||||||
layout(location = 0) in vec2 vertex;
|
layout(location = 0) in vec2 vertex;
|
||||||
out vec2 uv;
|
out vec2 uv;
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
precision mediump float;
|
||||||
|
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
#define EGL_SCALE_AUTO 0
|
#define EGL_SCALE_AUTO 0
|
||||||
#define EGL_SCALE_NEAREST 1
|
#define EGL_SCALE_NEAREST 1
|
||||||
@@ -25,17 +23,13 @@ void main()
|
|||||||
switch (scaleAlgo)
|
switch (scaleAlgo)
|
||||||
{
|
{
|
||||||
case EGL_SCALE_NEAREST:
|
case EGL_SCALE_NEAREST:
|
||||||
{
|
|
||||||
vec2 ts = vec2(textureSize(sampler1, 0));
|
vec2 ts = vec2(textureSize(sampler1, 0));
|
||||||
color = texelFetch(sampler1, ivec2(uv * ts), 0);
|
color = texelFetch(sampler1, ivec2(uv * ts), 0);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case EGL_SCALE_LINEAR:
|
case EGL_SCALE_LINEAR:
|
||||||
{
|
|
||||||
color = texture(sampler1, uv);
|
color = texture(sampler1, uv);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cbMode > 0)
|
if (cbMode > 0)
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
precision mediump float;
|
||||||
|
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
in vec2 fragCoord;
|
in vec2 fragCoord;
|
||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
|
||||||
uniform sampler2D sampler1;
|
uniform sampler2D texture;
|
||||||
uniform vec3 uConfig;
|
uniform vec3 uConfig;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
@@ -15,7 +13,7 @@ void main()
|
|||||||
float vOffset = uConfig.y;
|
float vOffset = uConfig.y;
|
||||||
float hOffset = uConfig.z;
|
float hOffset = uConfig.z;
|
||||||
|
|
||||||
vec2 inRes = vec2(textureSize(sampler1, 0));
|
vec2 inRes = vec2(textureSize(texture, 0));
|
||||||
ivec2 point = ivec2(
|
ivec2 point = ivec2(
|
||||||
(floor((fragCoord * inRes) / pixelSize) * pixelSize) +
|
(floor((fragCoord * inRes) / pixelSize) * pixelSize) +
|
||||||
pixelSize / 2.0f
|
pixelSize / 2.0f
|
||||||
@@ -24,5 +22,5 @@ void main()
|
|||||||
point.x += int(pixelSize * hOffset);
|
point.x += int(pixelSize * hOffset);
|
||||||
point.y += int(pixelSize * vOffset);
|
point.y += int(pixelSize * vOffset);
|
||||||
|
|
||||||
fragColor = texelFetch(sampler1, point, 0);
|
fragColor = texelFetch(texture, point, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
precision mediump float;
|
||||||
|
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
#define PI 3.141592653589793
|
#define PI 3.141592653589793
|
||||||
|
|
||||||
in vec2 fragCoord;
|
in vec2 fragCoord;
|
||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
|
||||||
uniform sampler2D sampler1;
|
uniform sampler2D texture;
|
||||||
float sinc(float x)
|
float sinc(float x)
|
||||||
{
|
{
|
||||||
return x == 0.0 ? 1.0 : sin(x * PI) / (x * PI);
|
return x == 0.0 ? 1.0 : sin(x * PI) / (x * PI);
|
||||||
@@ -26,7 +24,7 @@ float lanczos(vec2 v)
|
|||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec2 size = vec2(textureSize(sampler1, 0));
|
vec2 size = vec2(textureSize(texture, 0));
|
||||||
vec2 pos = fragCoord * size;
|
vec2 pos = fragCoord * size;
|
||||||
vec2 invSize = 1.0 / size;
|
vec2 invSize = 1.0 / size;
|
||||||
vec2 uvc = floor(pos) + vec2(0.5, 0.5);
|
vec2 uvc = floor(pos) + vec2(0.5, 0.5);
|
||||||
@@ -56,7 +54,7 @@ void main()
|
|||||||
|
|
||||||
vec3 color = vec3(0.0);
|
vec3 color = vec3(0.0);
|
||||||
for (int i = 0; i < 9; ++i)
|
for (int i = 0; i < 9; ++i)
|
||||||
color += texture(sampler1, uvs[i] * invSize).rgb * factors[i];
|
color += texture2D(texture, uvs[i] * invSize).rgb * factors[i];
|
||||||
|
|
||||||
fragColor = vec4(color, 1.0);
|
fragColor = vec4(color, 1.0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
precision mediump float;
|
||||||
|
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
in vec2 fragCoord;
|
in vec2 fragCoord;
|
||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
|
||||||
uniform sampler2D sampler1;
|
uniform sampler2D texture;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
fragColor = texture(sampler1, fragCoord);
|
fragColor = texture2D(texture, fragCoord);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
precision mediump float;
|
||||||
|
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
|
||||||
in vec2 fragCoord;
|
in vec2 fragCoord;
|
||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
|
||||||
uniform sampler2D sampler1;
|
uniform sampler2D texture;
|
||||||
uniform uvec4 uConsts[2];
|
uniform uvec4 uConsts[2];
|
||||||
|
|
||||||
#define A_GPU 1
|
#define A_GPU 1
|
||||||
@@ -18,7 +16,7 @@ uniform uvec4 uConsts[2];
|
|||||||
|
|
||||||
vec3 imageLoad(ivec2 point)
|
vec3 imageLoad(ivec2 point)
|
||||||
{
|
{
|
||||||
return texelFetch(sampler1, point, 0).rgb;
|
return texelFetch(texture, point, 0).rgb;
|
||||||
}
|
}
|
||||||
|
|
||||||
AF3 CasLoad(ASU2 p)
|
AF3 CasLoad(ASU2 p)
|
||||||
@@ -32,7 +30,7 @@ void CasInput(inout AF1 r,inout AF1 g,inout AF1 b) {}
|
|||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec2 res = vec2(textureSize(sampler1, 0));
|
vec2 res = vec2(textureSize(texture, 0));
|
||||||
uvec2 point = uvec2(fragCoord * res);
|
uvec2 point = uvec2(fragCoord * res);
|
||||||
|
|
||||||
CasFilter(
|
CasFilter(
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
#extension GL_OES_EGL_image_external_essl3 : enable
|
precision mediump float;
|
||||||
|
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
|
||||||
in vec2 fragCoord;
|
in vec2 fragCoord;
|
||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
|
||||||
uniform sampler2D sampler1;
|
uniform sampler2D texture;
|
||||||
uniform vec2 uOutRes;
|
uniform vec2 uOutRes;
|
||||||
uniform uvec4 uConsts[4];
|
uniform uvec4 uConsts[4];
|
||||||
|
|
||||||
@@ -20,9 +18,20 @@ uniform uvec4 uConsts[4];
|
|||||||
|
|
||||||
#define FSR_EASU_F 1
|
#define FSR_EASU_F 1
|
||||||
|
|
||||||
AF4 FsrEasuRF(AF2 p){return AF4(textureGather(sampler1, p, 0));}
|
vec4 _textureGather(sampler2D tex, vec2 uv, int comp)
|
||||||
AF4 FsrEasuGF(AF2 p){return AF4(textureGather(sampler1, p, 1));}
|
{
|
||||||
AF4 FsrEasuBF(AF2 p){return AF4(textureGather(sampler1, p, 2));}
|
vec2 res = vec2(textureSize(tex, 0));
|
||||||
|
ivec2 p = ivec2((uv * res) - 0.5f);
|
||||||
|
vec4 c0 = texelFetchOffset(tex, p, 0, ivec2(0,1));
|
||||||
|
vec4 c1 = texelFetchOffset(tex, p, 0, ivec2(1,1));
|
||||||
|
vec4 c2 = texelFetchOffset(tex, p, 0, ivec2(1,0));
|
||||||
|
vec4 c3 = texelFetchOffset(tex, p, 0, ivec2(0,0));
|
||||||
|
return vec4(c0[comp], c1[comp], c2[comp],c3[comp]);
|
||||||
|
}
|
||||||
|
|
||||||
|
AF4 FsrEasuRF(AF2 p){return AF4(_textureGather(texture, p, 0));}
|
||||||
|
AF4 FsrEasuGF(AF2 p){return AF4(_textureGather(texture, p, 1));}
|
||||||
|
AF4 FsrEasuBF(AF2 p){return AF4(_textureGather(texture, p, 2));}
|
||||||
|
|
||||||
#include "ffx_fsr1.h"
|
#include "ffx_fsr1.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
#version 300 es
|
#version 300 es
|
||||||
precision highp float;
|
precision mediump float;
|
||||||
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
|
||||||
in vec2 fragCoord;
|
in vec2 fragCoord;
|
||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
|
|
||||||
uniform sampler2D sampler1;
|
uniform sampler2D texture;
|
||||||
uniform uvec4 uConsts;
|
uniform uvec4 uConsts;
|
||||||
|
|
||||||
#define A_GPU 1
|
#define A_GPU 1
|
||||||
@@ -15,7 +15,7 @@ uniform uvec4 uConsts;
|
|||||||
|
|
||||||
#include "ffx_a.h"
|
#include "ffx_a.h"
|
||||||
|
|
||||||
AF4 FsrRcasLoadF(ASU2 p) { return texelFetch(sampler1, ASU2(p), 0); }
|
AF4 FsrRcasLoadF(ASU2 p) { return texelFetch(texture, ASU2(p), 0); }
|
||||||
void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b) {}
|
void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b) {}
|
||||||
|
|
||||||
#define FSR_RCAS_F 1
|
#define FSR_RCAS_F 1
|
||||||
@@ -24,7 +24,7 @@ void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b) {}
|
|||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec2 inRes = vec2(textureSize(sampler1, 0));
|
vec2 inRes = vec2(textureSize(texture, 0));
|
||||||
uvec2 point = uvec2(fragCoord * (inRes + 0.5f));
|
uvec2 point = uvec2(fragCoord * (inRes + 0.5f));
|
||||||
|
|
||||||
FsrRcasF(fragColor.r, fragColor.g, fragColor.b, point, uConsts);
|
FsrRcasF(fragColor.r, fragColor.g, fragColor.b, point, uConsts);
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
#include "common/framebuffer.h"
|
#include "common/framebuffer.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/array.h"
|
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <EGL/eglext.h>
|
#include <EGL/eglext.h>
|
||||||
@@ -77,7 +76,6 @@ bool egl_textureInit(EGL_Texture ** texture_, EGLDisplay * display,
|
|||||||
glSamplerParameteri(this->sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glSamplerParameteri(this->sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glSamplerParameteri(this->sampler, GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE);
|
glSamplerParameteri(this->sampler, GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE);
|
||||||
glSamplerParameteri(this->sampler, GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE);
|
glSamplerParameteri(this->sampler, GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +203,14 @@ enum EGL_TexStatus egl_textureProcess(EGL_Texture * this)
|
|||||||
|
|
||||||
enum EGL_TexStatus egl_textureBind(EGL_Texture * this)
|
enum EGL_TexStatus egl_textureBind(EGL_Texture * this)
|
||||||
{
|
{
|
||||||
|
GLuint tex;
|
||||||
|
EGL_TexStatus status;
|
||||||
|
|
||||||
|
if ((status = this->ops.get(this, &tex)) != EGL_TEX_STATUS_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, tex);
|
||||||
glBindSampler(0, this->sampler);
|
glBindSampler(0, this->sampler);
|
||||||
return this->ops.bind(this);
|
return EGL_TEX_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,9 +93,6 @@ typedef struct EGL_TextureOps
|
|||||||
|
|
||||||
/* get the texture for use */
|
/* get the texture for use */
|
||||||
enum EGL_TexStatus (*get)(EGL_Texture * texture, GLuint * tex);
|
enum EGL_TexStatus (*get)(EGL_Texture * texture, GLuint * tex);
|
||||||
|
|
||||||
/* bind the texture for use */
|
|
||||||
enum EGL_TexStatus (*bind)(EGL_Texture * texture);
|
|
||||||
}
|
}
|
||||||
EGL_TextureOps;
|
EGL_TextureOps;
|
||||||
|
|
||||||
|
|||||||
@@ -292,19 +292,6 @@ EGL_TexStatus egl_texBufferStreamGet(EGL_Texture * texture, GLuint * tex)
|
|||||||
return EGL_TEX_STATUS_OK;
|
return EGL_TEX_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
EGL_TexStatus egl_texBufferBind(EGL_Texture * texture)
|
|
||||||
{
|
|
||||||
GLuint tex;
|
|
||||||
EGL_TexStatus status;
|
|
||||||
|
|
||||||
if ((status = texture->ops.get(texture, &tex)) != EGL_TEX_STATUS_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, tex);
|
|
||||||
return EGL_TEX_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const EGL_TextureOps EGL_TextureBuffer =
|
const EGL_TextureOps EGL_TextureBuffer =
|
||||||
{
|
{
|
||||||
.init = egl_texBufferInit,
|
.init = egl_texBufferInit,
|
||||||
@@ -312,8 +299,7 @@ const EGL_TextureOps EGL_TextureBuffer =
|
|||||||
.setup = egl_texBufferSetup,
|
.setup = egl_texBufferSetup,
|
||||||
.update = egl_texBufferUpdate,
|
.update = egl_texBufferUpdate,
|
||||||
.process = egl_texBufferProcess,
|
.process = egl_texBufferProcess,
|
||||||
.get = egl_texBufferGet,
|
.get = egl_texBufferGet
|
||||||
.bind = egl_texBufferBind
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const EGL_TextureOps EGL_TextureBufferStream =
|
const EGL_TextureOps EGL_TextureBufferStream =
|
||||||
@@ -323,6 +309,5 @@ const EGL_TextureOps EGL_TextureBufferStream =
|
|||||||
.setup = egl_texBufferStreamSetup,
|
.setup = egl_texBufferStreamSetup,
|
||||||
.update = egl_texBufferStreamUpdate,
|
.update = egl_texBufferStreamUpdate,
|
||||||
.process = egl_texBufferStreamProcess,
|
.process = egl_texBufferStreamProcess,
|
||||||
.get = egl_texBufferStreamGet,
|
.get = egl_texBufferStreamGet
|
||||||
.bind = egl_texBufferBind
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ void egl_texBufferFree(EGL_Texture * texture_);
|
|||||||
bool egl_texBufferSetup(EGL_Texture * texture_, const EGL_TexSetup * setup);
|
bool egl_texBufferSetup(EGL_Texture * texture_, const EGL_TexSetup * setup);
|
||||||
EGL_TexStatus egl_texBufferProcess(EGL_Texture * texture_);
|
EGL_TexStatus egl_texBufferProcess(EGL_Texture * texture_);
|
||||||
EGL_TexStatus egl_texBufferGet(EGL_Texture * texture_, GLuint * tex);
|
EGL_TexStatus egl_texBufferGet(EGL_Texture * texture_, GLuint * tex);
|
||||||
EGL_TexStatus egl_texBufferBind(EGL_Texture * texture_);
|
|
||||||
|
|
||||||
bool egl_texBufferStreamInit(EGL_Texture ** texture_, EGL_TexType type,
|
bool egl_texBufferStreamInit(EGL_Texture ** texture_, EGL_TexType type,
|
||||||
EGLDisplay * display);
|
EGLDisplay * display);
|
||||||
|
|||||||
@@ -46,26 +46,12 @@ EGL_TextureOps EGL_TextureDMABUF;
|
|||||||
|
|
||||||
// internal functions
|
// internal functions
|
||||||
|
|
||||||
static void egl_texDMABUFCleanup(EGL_Texture * texture)
|
static void egl_texDMABUFCleanup(TexDMABUF * this)
|
||||||
{
|
{
|
||||||
TextureBuffer * parent = UPCAST(TextureBuffer, texture);
|
|
||||||
TexDMABUF * this = UPCAST(TexDMABUF , parent);
|
|
||||||
|
|
||||||
struct FdImage * image;
|
struct FdImage * image;
|
||||||
vector_forEachRef(image, &this->images)
|
vector_forEachRef(image, &this->images)
|
||||||
g_egl_dynProcs.eglDestroyImage(this->display, image->image);
|
g_egl_dynProcs.eglDestroyImage(this->display, image->image);
|
||||||
vector_clear(&this->images);
|
vector_clear(&this->images);
|
||||||
|
|
||||||
egl_texUtilFreeBuffers(parent->buf, parent->texCount);
|
|
||||||
|
|
||||||
if (parent->tex[0])
|
|
||||||
glDeleteTextures(parent->texCount, parent->tex);
|
|
||||||
|
|
||||||
if (parent->sync)
|
|
||||||
{
|
|
||||||
glDeleteSync(parent->sync);
|
|
||||||
parent->sync = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// dmabuf functions
|
// dmabuf functions
|
||||||
@@ -106,7 +92,7 @@ static void egl_texDMABUFFree(EGL_Texture * texture)
|
|||||||
TextureBuffer * parent = UPCAST(TextureBuffer, texture);
|
TextureBuffer * parent = UPCAST(TextureBuffer, texture);
|
||||||
TexDMABUF * this = UPCAST(TexDMABUF , parent);
|
TexDMABUF * this = UPCAST(TexDMABUF , parent);
|
||||||
|
|
||||||
egl_texDMABUFCleanup(texture);
|
egl_texDMABUFCleanup(this);
|
||||||
vector_destroy(&this->images);
|
vector_destroy(&this->images);
|
||||||
|
|
||||||
egl_texBufferFree(&parent->base);
|
egl_texBufferFree(&parent->base);
|
||||||
@@ -116,27 +102,11 @@ static void egl_texDMABUFFree(EGL_Texture * texture)
|
|||||||
static bool egl_texDMABUFSetup(EGL_Texture * texture, const EGL_TexSetup * setup)
|
static bool egl_texDMABUFSetup(EGL_Texture * texture, const EGL_TexSetup * setup)
|
||||||
{
|
{
|
||||||
TextureBuffer * parent = UPCAST(TextureBuffer, texture);
|
TextureBuffer * parent = UPCAST(TextureBuffer, texture);
|
||||||
|
TexDMABUF * this = UPCAST(TexDMABUF , parent);
|
||||||
|
|
||||||
egl_texDMABUFCleanup(texture);
|
egl_texDMABUFCleanup(this);
|
||||||
|
|
||||||
glGenTextures(parent->texCount, parent->tex);
|
return egl_texBufferSetup(&parent->base, setup);
|
||||||
for(int i = 0; i < parent->texCount; ++i)
|
|
||||||
{
|
|
||||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, parent->tex[i]);
|
|
||||||
glTexImage2D(GL_TEXTURE_EXTERNAL_OES,
|
|
||||||
0,
|
|
||||||
texture->format.intFormat,
|
|
||||||
texture->format.width,
|
|
||||||
texture->format.height,
|
|
||||||
0,
|
|
||||||
texture->format.format,
|
|
||||||
texture->format.dataType,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
|
|
||||||
parent->rIndex = -1;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool egl_texDMABUFUpdate(EGL_Texture * texture,
|
static bool egl_texDMABUFUpdate(EGL_Texture * texture,
|
||||||
@@ -203,8 +173,8 @@ static bool egl_texDMABUFUpdate(EGL_Texture * texture,
|
|||||||
|
|
||||||
INTERLOCKED_SECTION(parent->copyLock,
|
INTERLOCKED_SECTION(parent->copyLock,
|
||||||
{
|
{
|
||||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, parent->tex[parent->bufIndex]);
|
glBindTexture(GL_TEXTURE_2D, parent->tex[parent->bufIndex]);
|
||||||
g_egl_dynProcs.glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
|
g_egl_dynProcs.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
|
||||||
|
|
||||||
if (parent->sync)
|
if (parent->sync)
|
||||||
glDeleteSync(parent->sync);
|
glDeleteSync(parent->sync);
|
||||||
@@ -268,18 +238,6 @@ static EGL_TexStatus egl_texDMABUFGet(EGL_Texture * texture, GLuint * tex)
|
|||||||
return EGL_TEX_STATUS_OK;
|
return EGL_TEX_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static EGL_TexStatus egl_texDMABUFBind(EGL_Texture * texture)
|
|
||||||
{
|
|
||||||
GLuint tex;
|
|
||||||
EGL_TexStatus status;
|
|
||||||
|
|
||||||
if ((status = egl_texDMABUFGet(texture, &tex)) != EGL_TEX_STATUS_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex);
|
|
||||||
return EGL_TEX_STATUS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
EGL_TextureOps EGL_TextureDMABUF =
|
EGL_TextureOps EGL_TextureDMABUF =
|
||||||
{
|
{
|
||||||
.init = egl_texDMABUFInit,
|
.init = egl_texDMABUFInit,
|
||||||
@@ -287,6 +245,5 @@ EGL_TextureOps EGL_TextureDMABUF =
|
|||||||
.setup = egl_texDMABUFSetup,
|
.setup = egl_texDMABUFSetup,
|
||||||
.update = egl_texDMABUFUpdate,
|
.update = egl_texDMABUFUpdate,
|
||||||
.process = egl_texDMABUFProcess,
|
.process = egl_texDMABUFProcess,
|
||||||
.get = egl_texDMABUFGet,
|
.get = egl_texDMABUFGet
|
||||||
.bind = egl_texDMABUFBind
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -147,6 +147,5 @@ EGL_TextureOps EGL_TextureFrameBuffer =
|
|||||||
.setup = egl_texFBSetup,
|
.setup = egl_texFBSetup,
|
||||||
.update = egl_texFBUpdate,
|
.update = egl_texFBUpdate,
|
||||||
.process = egl_texBufferStreamProcess,
|
.process = egl_texBufferStreamProcess,
|
||||||
.get = egl_texBufferStreamGet,
|
.get = egl_texBufferStreamGet
|
||||||
.bind = egl_texBufferBind
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -478,10 +478,11 @@ void core_handleMouseNormal(double ex, double ey)
|
|||||||
if (!g_state.stopVideo &&
|
if (!g_state.stopVideo &&
|
||||||
g_state.kvmfrFeatures & KVMFR_FEATURE_SETCURSORPOS)
|
g_state.kvmfrFeatures & KVMFR_FEATURE_SETCURSORPOS)
|
||||||
{
|
{
|
||||||
const KVMFRSetCursorPos msg = {
|
const KVMFRMessage_SetCursorPos msg = {
|
||||||
.msg.type = KVMFR_MESSAGE_SETCURSORPOS,
|
.msg.type = KVMFR_MESSAGE_SETCURSORPOS,
|
||||||
.x = round(guest.x),
|
.msg.clientID = g_state.clientID,
|
||||||
.y = round(guest.y)
|
.x = round(guest.x),
|
||||||
|
.y = round(guest.y)
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t setPosSerial;
|
uint32_t setPosSerial;
|
||||||
|
|||||||
@@ -1434,7 +1434,7 @@ restart:
|
|||||||
}
|
}
|
||||||
|
|
||||||
status = lgmpClientSessionInit(g_state.lgmp, &udataSize, (uint8_t **)&udata,
|
status = lgmpClientSessionInit(g_state.lgmp, &udataSize, (uint8_t **)&udata,
|
||||||
NULL);
|
&g_state.clientID);
|
||||||
switch(status)
|
switch(status)
|
||||||
{
|
{
|
||||||
case LGMP_OK:
|
case LGMP_OK:
|
||||||
@@ -1814,10 +1814,6 @@ int main(int argc, char * argv[])
|
|||||||
for(unsigned int i = 0; i < LG_DISPLAYSERVER_COUNT; ++i)
|
for(unsigned int i = 0; i < LG_DISPLAYSERVER_COUNT; ++i)
|
||||||
LG_DisplayServers[i]->setup();
|
LG_DisplayServers[i]->setup();
|
||||||
|
|
||||||
for(unsigned int i = 0; i < LG_AUDIODEV_COUNT; ++i)
|
|
||||||
if (LG_AudioDevs[i]->earlyInit)
|
|
||||||
LG_AudioDevs[i]->earlyInit();
|
|
||||||
|
|
||||||
if (!config_load(argc, argv))
|
if (!config_load(argc, argv))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
#include "dynamic/displayservers.h"
|
#include "dynamic/displayservers.h"
|
||||||
#include "dynamic/renderers.h"
|
#include "dynamic/renderers.h"
|
||||||
#include "dynamic/audiodev.h"
|
|
||||||
|
|
||||||
#include "common/thread.h"
|
#include "common/thread.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
@@ -122,6 +121,7 @@ struct AppState
|
|||||||
|
|
||||||
struct IVSHMEM shm;
|
struct IVSHMEM shm;
|
||||||
PLGMPClient lgmp;
|
PLGMPClient lgmp;
|
||||||
|
uint32_t clientID;
|
||||||
PLGMPClientQueue pointerQueue;
|
PLGMPClientQueue pointerQueue;
|
||||||
LG_Lock pointerQueueLock;
|
LG_Lock pointerQueueLock;
|
||||||
KVMFRFeatureFlags kvmfrFeatures;
|
KVMFRFeatureFlags kvmfrFeatures;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define KVMFR_MAGIC "KVMFR---"
|
#define KVMFR_MAGIC "KVMFR---"
|
||||||
#define KVMFR_VERSION 19
|
#define KVMFR_VERSION 20
|
||||||
|
|
||||||
#define KVMFR_MAX_DAMAGE_RECTS 64
|
#define KVMFR_MAX_DAMAGE_RECTS 64
|
||||||
|
|
||||||
@@ -56,7 +56,8 @@ typedef uint32_t KVMFRFeatureFlags;
|
|||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
KVMFR_MESSAGE_SETCURSORPOS
|
KVMFR_MESSAGE_SETCURSORPOS,
|
||||||
|
KVMFR_MESSAGE_FRAME_TIME
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uint32_t KVMFRMessageType;
|
typedef uint32_t KVMFRMessageType;
|
||||||
@@ -137,6 +138,8 @@ typedef struct KVMFRFrame
|
|||||||
{
|
{
|
||||||
uint32_t formatVer; // the frame format version number
|
uint32_t formatVer; // the frame format version number
|
||||||
uint32_t frameSerial; // the unique frame number
|
uint32_t frameSerial; // the unique frame number
|
||||||
|
uint64_t frameTimeUs; // when the capture was started
|
||||||
|
uint64_t frameElapsedUs; // total time elapsed to capture the frame
|
||||||
FrameType type; // the frame data type
|
FrameType type; // the frame data type
|
||||||
uint32_t screenWidth; // the client's screen width
|
uint32_t screenWidth; // the client's screen width
|
||||||
uint32_t screenHeight; // the client's screen height
|
uint32_t screenHeight; // the client's screen height
|
||||||
@@ -155,14 +158,28 @@ KVMFRFrame;
|
|||||||
typedef struct KVMFRMessage
|
typedef struct KVMFRMessage
|
||||||
{
|
{
|
||||||
KVMFRMessageType type;
|
KVMFRMessageType type;
|
||||||
|
uint32_t clientID;
|
||||||
}
|
}
|
||||||
KVMFRMessage;
|
KVMFRMessage;
|
||||||
|
|
||||||
typedef struct KVMFRSetCursorPos
|
typedef struct KVMFRMessage_SetCursorPos
|
||||||
{
|
{
|
||||||
KVMFRMessage msg;
|
KVMFRMessage msg;
|
||||||
int32_t x, y;
|
int32_t x, y;
|
||||||
}
|
}
|
||||||
KVMFRSetCursorPos;
|
KVMFRMessage_SetCursorPos;
|
||||||
|
|
||||||
|
typedef struct KVMFRMessage_FrameTime
|
||||||
|
{
|
||||||
|
KVMFRMessage msg;
|
||||||
|
/* this is the desired time to start the next capture operation where zero is
|
||||||
|
* immediate. This is only a hint to the host application and may not be
|
||||||
|
* honored. The value provided should be offset from the latest frame's
|
||||||
|
* frameTimeUs. When multiple clients are sending this message, the one with
|
||||||
|
* the lowest value will be used.
|
||||||
|
*/
|
||||||
|
uint64_t frameTimeUs;
|
||||||
|
}
|
||||||
|
KVMFRMessage_FrameTime;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -316,55 +316,43 @@ static bool nvfbc_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int adapterIndex = option_get_int("nvfbc", "adapterIndex");
|
int adapterIndex = option_get_int("nvfbc", "adapterIndex");
|
||||||
|
// NOTE: Calling this on hardware that doesn't support NvFBC such as GeForce
|
||||||
bool created = false;
|
// causes a substantial performance pentalty even if it fails! As such we only
|
||||||
for(int retry = 0; retry < 2; ++retry)
|
// attempt NvFBC as a last resort, or if configured via the app:capture
|
||||||
|
// option.
|
||||||
|
if (adapterIndex < 0)
|
||||||
{
|
{
|
||||||
// NOTE: Calling this on hardware that doesn't support NvFBC such as GeForce
|
IDirect3D9 * d3d = Direct3DCreate9(D3D_SDK_VERSION);
|
||||||
// causes a substantial performance pentalty even if it fails! As such we only
|
int adapterCount = IDirect3D9_GetAdapterCount(d3d);
|
||||||
// attempt NvFBC as a last resort, or if configured via the app:capture
|
for(int i = 0; i < adapterCount; ++i)
|
||||||
// option.
|
{
|
||||||
|
D3DADAPTER_IDENTIFIER9 ident;
|
||||||
|
IDirect3D9_GetAdapterIdentifier(d3d, i, 0, &ident);
|
||||||
|
if (ident.VendorId != 0x10DE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (NvFBCToSysCreate(i, privData, privDataLen, &this->nvfbc,
|
||||||
|
&this->maxWidth, &this->maxHeight))
|
||||||
|
{
|
||||||
|
adapterIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IDirect3D9_Release(d3d);
|
||||||
|
|
||||||
if (adapterIndex < 0)
|
if (adapterIndex < 0)
|
||||||
{
|
{
|
||||||
IDirect3D9 * d3d = Direct3DCreate9(D3D_SDK_VERSION);
|
free(privData);
|
||||||
int adapterCount = IDirect3D9_GetAdapterCount(d3d);
|
return false;
|
||||||
for(int i = 0; i < adapterCount; ++i)
|
|
||||||
{
|
|
||||||
D3DADAPTER_IDENTIFIER9 ident;
|
|
||||||
IDirect3D9_GetAdapterIdentifier(d3d, i, 0, &ident);
|
|
||||||
if (ident.VendorId != 0x10DE)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (NvFBCToSysCreate(i, privData, privDataLen, &this->nvfbc,
|
|
||||||
&this->maxWidth, &this->maxHeight))
|
|
||||||
{
|
|
||||||
adapterIndex = i;
|
|
||||||
created = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IDirect3D9_Release(d3d);
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
if (!NvFBCToSysCreate(adapterIndex, privData, privDataLen, &this->nvfbc, &this->maxWidth, &this->maxHeight))
|
||||||
{
|
{
|
||||||
if (!NvFBCToSysCreate(adapterIndex, privData, privDataLen, &this->nvfbc, &this->maxWidth, &this->maxHeight))
|
free(privData);
|
||||||
continue;
|
return false;
|
||||||
created = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (created)
|
|
||||||
break;
|
|
||||||
|
|
||||||
//1000ms delay before retry
|
|
||||||
nsleep(1000000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!created)
|
|
||||||
{
|
|
||||||
free(privData);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int diffRes = option_get_int("nvfbc", "diffRes");
|
int diffRes = option_get_int("nvfbc", "diffRes");
|
||||||
enum DiffMapBlockSize blockSize;
|
enum DiffMapBlockSize blockSize;
|
||||||
NvFBCGetDiffMapBlockSize(diffRes, &blockSize, &this->diffShift, privData, privDataLen);
|
NvFBCGetDiffMapBlockSize(diffRes, &blockSize, &this->diffShift, privData, privDataLen);
|
||||||
|
|||||||
@@ -526,13 +526,7 @@ bool app_init(void)
|
|||||||
|
|
||||||
// redirect stderr to a file
|
// redirect stderr to a file
|
||||||
if (logFile && strcmp(logFile, "stderr") != 0)
|
if (logFile && strcmp(logFile, "stderr") != 0)
|
||||||
{
|
freopen(logFile, "a", stderr);
|
||||||
DEBUG_INFO("Logs will be written to: %s", logFile);
|
|
||||||
DEBUG_INFO("Please see there for any further information");
|
|
||||||
|
|
||||||
if (!freopen(logFile, "a", stderr))
|
|
||||||
DEBUG_WARN("Failed to open log file, will log to stderr");
|
|
||||||
}
|
|
||||||
|
|
||||||
// always flush stderr
|
// always flush stderr
|
||||||
setbuf(stderr, NULL);
|
setbuf(stderr, NULL);
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ struct app
|
|||||||
unsigned int frameIndex;
|
unsigned int frameIndex;
|
||||||
bool frameValid;
|
bool frameValid;
|
||||||
uint32_t frameSerial;
|
uint32_t frameSerial;
|
||||||
|
uint64_t frameTimeUs;
|
||||||
|
|
||||||
CaptureInterface * iface;
|
CaptureInterface * iface;
|
||||||
|
|
||||||
@@ -268,6 +269,7 @@ static bool sendFrame(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fi->formatVer = frame.formatVer;
|
fi->formatVer = frame.formatVer;
|
||||||
|
fi->frameTimeUs = app.frameTimeUs;
|
||||||
fi->frameSerial = app.frameSerial++;
|
fi->frameSerial = app.frameSerial++;
|
||||||
fi->screenWidth = frame.screenWidth;
|
fi->screenWidth = frame.screenWidth;
|
||||||
fi->screenHeight = frame.screenHeight;
|
fi->screenHeight = frame.screenHeight;
|
||||||
@@ -295,6 +297,11 @@ static bool sendFrame(void)
|
|||||||
FrameBuffer * fb = (FrameBuffer *)(((uint8_t*)fi) + fi->offset);
|
FrameBuffer * fb = (FrameBuffer *)(((uint8_t*)fi) + fi->offset);
|
||||||
framebuffer_prepare(fb);
|
framebuffer_prepare(fb);
|
||||||
|
|
||||||
|
// calculate the elapsed time as late as possible, note that this does not
|
||||||
|
// take into account the memory copy time and the client's that care about
|
||||||
|
// this value will need to take this into account
|
||||||
|
fi->frameElapsedUs = microtime() - app.frameTimeUs;
|
||||||
|
|
||||||
/* we post and then get the frame, this is intentional! */
|
/* we post and then get the frame, this is intentional! */
|
||||||
if ((status = lgmpHostQueuePost(app.frameQueue, 0,
|
if ((status = lgmpHostQueuePost(app.frameQueue, 0,
|
||||||
app.frameMemory[app.frameIndex])) != LGMP_OK)
|
app.frameMemory[app.frameIndex])) != LGMP_OK)
|
||||||
@@ -748,7 +755,7 @@ int app_main(int argc, char * argv[])
|
|||||||
if (option_load(configFile))
|
if (option_load(configFile))
|
||||||
DEBUG_INFO("Configuration file loaded");
|
DEBUG_INFO("Configuration file loaded");
|
||||||
else
|
else
|
||||||
DEBUG_INFO("Configuration file not found or invalid, continuing anyway...");
|
DEBUG_INFO("Configuration file not found or invalid");
|
||||||
|
|
||||||
// parse the command line arguments
|
// parse the command line arguments
|
||||||
if (!option_parse(argc, argv))
|
if (!option_parse(argc, argv))
|
||||||
@@ -901,20 +908,20 @@ int app_main(int argc, char * argv[])
|
|||||||
LG_UNLOCK(app.pointerLock);
|
LG_UNLOCK(app.pointerLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint64_t delta = microtime() - previousFrameTime;
|
const uint64_t now = microtime();
|
||||||
|
const uint64_t delta = now - previousFrameTime;
|
||||||
if (delta < throttleUs)
|
if (delta < throttleUs)
|
||||||
{
|
{
|
||||||
const uint64_t us = throttleUs - delta;
|
nsleep((throttleUs - delta) * 1000);
|
||||||
// only delay if the time is reasonable
|
previousFrameTime = microtime();
|
||||||
if (us > 1000)
|
|
||||||
nsleep(us * 1000);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
previousFrameTime = now;
|
||||||
|
|
||||||
const uint64_t captureStart = microtime();
|
app.frameTimeUs = microtime();
|
||||||
switch(iface->capture())
|
switch(iface->capture())
|
||||||
{
|
{
|
||||||
case CAPTURE_RESULT_OK:
|
case CAPTURE_RESULT_OK:
|
||||||
previousFrameTime = captureStart;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CAPTURE_RESULT_TIMEOUT:
|
case CAPTURE_RESULT_TIMEOUT:
|
||||||
|
|||||||
2
obs/lg.c
2
obs/lg.c
@@ -421,7 +421,7 @@ static void lgUpdate(void * data, obs_data_t * settings)
|
|||||||
|
|
||||||
usleep(200000);
|
usleep(200000);
|
||||||
|
|
||||||
if (lgmpClientSessionInit(this->lgmp, &udataSize, (uint8_t **)&udata, NULL)
|
if (lgmpClientSessionInit(this->lgmp, &udataSize, (uint8_t **)&udata)
|
||||||
!= LGMP_OK)
|
!= LGMP_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user