Compare commits

...

10 Commits

Author SHA1 Message Date
Geoffrey McRae
b4b4a37b2b [client] egl: switch to using GL_TEXTURE_EXTERNAL_OES for DMABUF
According to Erik @ NVidia the open source NVidia driver will not
create a EGLImage from a DMABUF if the target is not
GL_TEXTURE_EXTERNAL_OES. This change set converts the dmabuf texture
from GL_TEXTURE_2D to GL_TEXTURE_EXTERNAL_OES and at runtime performs a
global search & replace on fragment shaders as needed to remain
compatible, replacing `sampler2D` with `samplerExternalOES`.

Ref: https://github.com/NVIDIA/open-gpu-kernel-modules/discussions/243#discussioncomment-3283415
2023-03-09 09:20:01 +11:00
Geoffrey McRae
bbc9204bfe [client] egl: ensure the preprocessed files have a null terminator 2023-03-09 09:15:39 +11:00
Geoffrey McRae
894b8b0c22 [client] x11: generate synthetic EnterNotify event on cursor leave
If the cursor was grabbed the window the cursor moves over when it is
ungrabbed will recieve an EnterNotify event with the mode of
NotifyUngrab, unfortunatly some window manages such as i3 will ignore
this message and as such focus follows mouse will not function
correctly. This patch injects a normal EnterNotify to work around this
issue.
2023-03-05 16:42:47 +11:00
Geoffrey McRae
91b0cba145 [client] egl: switch from mediump to highp
This fixes a rounding issue on certain hardware (NVidia) which actually
implement mediump as half precision (16-bit) float. It's safe to assume
`highp` is available as if the GPU does not support it, then the shader
compiler will try to find a lower precision that is supported by the GPU
2023-03-05 14:10:21 +11:00
Geoffrey McRae
2f48798db9 [client] wayland: check for failure of wl_display_connect 2023-02-28 23:38:44 +11:00
Geoffrey McRae
254b370bbf [client] audio/pipewire: fix compilation under clang 2023-01-24 13:46:22 +11:00
Geoffrey McRae
86efc47505 [client] audio/pipewire: PW_KEY_TARGET_OBJECT only exists as of 0.3.44 2023-01-24 13:43:17 +11:00
Geoffrey McRae
b559d6b9bc [client] audio/pipewire: add options to set the default out/rec devices 2023-01-24 13:35:25 +11:00
Geoffrey McRae
48cd0c3789 [client] audio: add missing earlyInit call for audio devs 2023-01-24 13:35:18 +11:00
Geoffrey McRae
6f8e6f9a19 [client] x11: catch and print details of X11 errors with a backtrace 2023-01-05 17:33:01 +11:00
39 changed files with 519 additions and 207 deletions

View File

@@ -28,6 +28,7 @@
#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
{ {
@@ -129,6 +130,29 @@ 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);
@@ -221,9 +245,8 @@ 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(
pw.loop, struct pw_properties * props =
"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",
@@ -231,7 +254,22 @@ 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
); );
@@ -449,17 +487,30 @@ 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;
pw_thread_loop_lock(pw.thread); struct pw_properties * props =
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
); );
@@ -544,6 +595,7 @@ 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 =

View File

@@ -71,12 +71,16 @@ 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;

View File

@@ -242,12 +242,31 @@ 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;
@@ -1152,6 +1171,46 @@ 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;
} }

View File

@@ -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)) vertex_code, vertex_size, fragment_code, fragment_size, false))
{ {
DEBUG_ERROR("Failed to compile the cursor shader"); DEBUG_ERROR("Failed to compile the cursor shader");
return false; return false;

View File

@@ -76,7 +76,8 @@ 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;

View File

@@ -46,6 +46,7 @@ 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;
@@ -57,7 +58,7 @@ struct EGL_Desktop
EGLDisplay * display; EGLDisplay * display;
EGL_Texture * texture; EGL_Texture * texture;
struct DesktopShader shader; struct DesktopShader dmaShader, shader;
EGL_DesktopRects * mesh; EGL_DesktopRects * mesh;
CountedBuffer * matrix; CountedBuffer * matrix;
@@ -92,7 +93,8 @@ 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))
@@ -100,7 +102,8 @@ 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;
} }
@@ -135,15 +138,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))
{
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");
@@ -157,6 +151,27 @@ 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");
@@ -207,7 +222,8 @@ void egl_desktopFree(EGL_Desktop ** desktop)
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 );
@@ -399,18 +415,17 @@ 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); width, height, outputWidth, outputHeight, desktop->useDMA);
unsigned int finalSizeX, finalSizeY; unsigned int finalSizeX, finalSizeY;
GLuint texture = egl_postProcessGetOutput(desktop->pp, EGL_Texture * 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);
glBindTexture(GL_TEXTURE_2D, texture); egl_textureBind(texture);
glBindSampler(0, tex->sampler);
if (finalSizeX > width || finalSizeY > height) if (finalSizeX > width || finalSizeY > height)
scaleType = EGL_DESKTOP_DOWNSCALE; scaleType = EGL_DESKTOP_DOWNSCALE;
@@ -435,7 +450,10 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
scaleAlgo = desktop->scaleAlgo; scaleAlgo = desktop->scaleAlgo;
} }
const struct DesktopShader * shader = &desktop->shader; const struct DesktopShader * shader =
desktop->useDMA && texture == desktop->texture ?
&desktop->dmaShader : &desktop->shader;
EGL_Uniform uniforms[] = EGL_Uniform uniforms[] =
{ {
{ {

View File

@@ -68,9 +68,11 @@ 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); unsigned int width, unsigned int height, bool useDMA);
/* 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 */
@@ -87,8 +89,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 */
GLuint (*run)(EGL_Filter * filter, EGL_FilterRects * rects, EGL_Texture * (*run)(EGL_Filter * filter, EGL_FilterRects * rects,
GLuint texture); EGL_Texture * 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 */
@@ -133,9 +135,10 @@ 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); return filter->ops.setup(filter, pixFmt, width, height, useDMA);
} }
static inline void egl_filterSetOutputResHint(EGL_Filter * filter, static inline void egl_filterSetOutputResHint(EGL_Filter * filter,
@@ -156,8 +159,8 @@ static inline bool egl_filterPrepare(EGL_Filter * filter)
return filter->ops.prepare(filter); return filter->ops.prepare(filter);
} }
static inline GLuint egl_filterRun(EGL_Filter * filter, static inline EGL_Texture * egl_filterRun(EGL_Filter * filter,
EGL_FilterRects * rects, GLuint texture) EGL_FilterRects * rects, EGL_Texture * texture)
{ {
return filter->ops.run(filter, rects, texture); return filter->ops.run(filter, rects, texture);
} }

View File

@@ -60,6 +60,7 @@ 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;
@@ -157,55 +158,26 @@ 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");
@@ -326,7 +298,8 @@ 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);
@@ -336,6 +309,48 @@ 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 &&
@@ -385,15 +400,15 @@ static bool egl_filterDownscalePrepare(EGL_Filter * filter)
return true; return true;
} }
static GLuint egl_filterDownscaleRun(EGL_Filter * filter, static EGL_Texture * egl_filterDownscaleRun(EGL_Filter * filter,
EGL_FilterRects * rects, GLuint texture) EGL_FilterRects * rects, EGL_Texture * 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);
glBindTexture(GL_TEXTURE_2D, texture); egl_textureBind(texture);
EGL_Shader * shader; EGL_Shader * shader;

View File

@@ -37,6 +37,7 @@ 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;
@@ -106,21 +107,14 @@ 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)
{ {
@@ -128,12 +122,6 @@ 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))
@@ -220,13 +208,35 @@ 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;
@@ -262,15 +272,15 @@ static bool egl_filterFFXCASPrepare(EGL_Filter * filter)
return true; return true;
} }
static GLuint egl_filterFFXCASRun(EGL_Filter * filter, static EGL_Texture * egl_filterFFXCASRun(EGL_Filter * filter,
EGL_FilterRects * rects, GLuint texture) EGL_FilterRects * rects, EGL_Texture * 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);
glBindTexture(GL_TEXTURE_2D, texture); egl_textureBind(texture);
glBindSampler(0, this->sampler); glBindSampler(0, this->sampler);
egl_shaderUse(this->shader); egl_shaderUse(this->shader);

View File

@@ -42,6 +42,7 @@ 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;
@@ -109,6 +110,8 @@ 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");
@@ -121,18 +124,10 @@ 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");
@@ -148,14 +143,6 @@ 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);
@@ -335,13 +322,37 @@ 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;
@@ -395,15 +406,15 @@ static bool egl_filterFFXFSR1Prepare(EGL_Filter * filter)
return true; return true;
} }
static GLuint egl_filterFFXFSR1Run(EGL_Filter * filter, static EGL_Texture * egl_filterFFXFSR1Run(EGL_Filter * filter,
EGL_FilterRects * rects, GLuint texture) EGL_FilterRects * rects, EGL_Texture * 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);
glBindTexture(GL_TEXTURE_2D, texture); egl_textureBind(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);
@@ -412,7 +423,7 @@ static GLuint 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);
glBindTexture(GL_TEXTURE_2D, texture); egl_textureBind(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);

View File

@@ -100,9 +100,7 @@ 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);
} }
GLuint egl_framebufferGetTexture(EGL_Framebuffer * this) EGL_Texture * egl_framebufferGetTexture(EGL_Framebuffer * this)
{ {
GLuint output; return this->tex;
egl_textureGet(this->tex, &output, NULL, NULL);
return output;
} }

View File

@@ -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);
GLuint egl_framebufferGetTexture(EGL_Framebuffer * this); EGL_Texture * egl_framebufferGetTexture(EGL_Framebuffer * this);

View File

@@ -10,4 +10,4 @@ function process(line, second) {
} }
} }
{ process($0, $2) } { process($0, $2) } END { print "\0"; }

View File

@@ -49,7 +49,7 @@ static const EGL_FilterOps * EGL_Filters[] =
struct EGL_PostProcess struct EGL_PostProcess
{ {
Vector filters; Vector filters;
GLuint output; EGL_Texture * 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) unsigned int targetX, unsigned int targetY, bool useDMA)
{ {
if (targetX == 0 && targetY == 0) if (targetX == 0 && targetY == 0)
DEBUG_FATAL("targetX || targetY == 0"); DEBUG_FATAL("targetX || targetY == 0");
@@ -614,8 +614,9 @@ 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;
GLuint texture; //TODO: clean this up
if (egl_textureGet(tex, &texture, &sizeX, &sizeY) != EGL_TEX_STATUS_OK) GLuint _unused;
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))
@@ -636,11 +637,12 @@ 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) || if (!egl_filterSetup(filter, tex->format.pixFmt, sizeX, sizeY, useDMA) ||
!egl_filterPrepare(filter)) !egl_filterPrepare(filter))
continue; continue;
@@ -651,6 +653,9 @@ 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;
@@ -659,7 +664,7 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
return true; return true;
} }
GLuint egl_postProcessGetOutput(EGL_PostProcess * this, EGL_Texture * egl_postProcessGetOutput(EGL_PostProcess * this,
unsigned int * outputX, unsigned int * outputY) unsigned int * outputX, unsigned int * outputY)
{ {
*outputX = this->outputX; *outputX = this->outputX;

View File

@@ -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); unsigned int targetX, unsigned int targetY, bool useDMA);
GLuint egl_postProcessGetOutput(EGL_PostProcess * this, EGL_Texture * egl_postProcessGetOutput(EGL_PostProcess * this,
unsigned int * outputX, unsigned int * outputY); unsigned int * outputX, unsigned int * outputY);

View File

@@ -64,7 +64,8 @@ void egl_shaderFree(EGL_Shader ** shader)
*shader = NULL; *shader = NULL;
} }
bool egl_shaderLoad(EGL_Shader * this, const char * vertex_file, const char * fragment_file) bool egl_shaderLoad(EGL_Shader * this,
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;
@@ -86,13 +87,16 @@ bool egl_shaderLoad(EGL_Shader * this, const char * vertex_file, const char * fr
DEBUG_INFO("Loaded fragment shader: %s", fragment_file); DEBUG_INFO("Loaded fragment shader: %s", fragment_file);
bool ret = egl_shaderCompile(this, vertex_code, vertex_size, fragment_code, fragment_size); bool ret = egl_shaderCompile(this,
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;
} }
bool egl_shaderCompile(EGL_Shader * this, const char * vertex_code, static bool 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)
@@ -204,6 +208,64 @@ bool egl_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);

View File

@@ -97,10 +97,11 @@ 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); const char * fragment_file, bool useDMA);
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);

View File

@@ -1,5 +1,5 @@
#version 300 es #version 300 es
precision mediump float; precision highp float;
layout(location = 0) in vec2 vertex; layout(location = 0) in vec2 vertex;
out vec2 fragCoord; out vec2 fragCoord;

View File

@@ -1,16 +1,21 @@
#if __VERSION__ == 300 #if __VERSION__ == 300
vec4 textureGather(sampler2D tex, vec2 uv, int comp) vec4 textureGather(sampler2D tex, vec2 uv, int comp)
{ {
vec4 c0 = textureOffset(tex, uv, ivec2(0,1)); vec2 res = vec2(textureSize(tex, 0));
vec4 c1 = textureOffset(tex, uv, ivec2(1,1)); ivec2 p = ivec2((uv * res) - 0.5f);
vec4 c2 = textureOffset(tex, uv, ivec2(1,0));
vec4 c3 = textureOffset(tex, uv, ivec2(0,0)); // NOTE: we can't use texelFecthOffset because sampler2D may actually be samplerExternalOES
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 = texture2D(tex, uv); vec4 c3 = texture(tex, uv);
return vec4(c3[comp], c3[comp], c3[comp],c3[comp]); return vec4(c3[comp], c3[comp], c3[comp],c3[comp]);
} }
#endif #endif

View File

@@ -1,5 +1,5 @@
#version 300 es #version 300 es
precision mediump float; precision highp 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;

View File

@@ -1,5 +1,5 @@
#version 300 es #version 300 es
precision mediump float; precision highp float;
in vec2 uv; in vec2 uv;
out vec4 color; out vec4 color;

View File

@@ -1,5 +1,5 @@
#version 300 es #version 300 es
precision mediump float; precision highp float;
#include "color_blind.h" #include "color_blind.h"

View File

@@ -1,5 +1,5 @@
#version 300 es #version 300 es
precision mediump float; precision highp float;
out vec4 color; out vec4 color;

View File

@@ -1,5 +1,5 @@
#version 300 es #version 300 es
precision mediump float; precision highp float;
layout(location = 0) in vec2 vertex; layout(location = 0) in vec2 vertex;
out vec2 uv; out vec2 uv;

View File

@@ -1,5 +1,7 @@
#version 300 es #version 300 es
precision mediump float; #extension GL_OES_EGL_image_external_essl3 : enable
precision highp float;
#define EGL_SCALE_AUTO 0 #define EGL_SCALE_AUTO 0
#define EGL_SCALE_NEAREST 1 #define EGL_SCALE_NEAREST 1
@@ -23,14 +25,18 @@ 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)
color = cbTransform(color, cbMode); color = cbTransform(color, cbMode);

View File

@@ -1,10 +1,12 @@
#version 300 es #version 300 es
precision mediump float; #extension GL_OES_EGL_image_external_essl3 : enable
precision highp float;
in vec2 fragCoord; in vec2 fragCoord;
out vec4 fragColor; out vec4 fragColor;
uniform sampler2D texture; uniform sampler2D sampler1;
uniform vec3 uConfig; uniform vec3 uConfig;
void main() void main()
@@ -13,7 +15,7 @@ void main()
float vOffset = uConfig.y; float vOffset = uConfig.y;
float hOffset = uConfig.z; float hOffset = uConfig.z;
vec2 inRes = vec2(textureSize(texture, 0)); vec2 inRes = vec2(textureSize(sampler1, 0));
ivec2 point = ivec2( ivec2 point = ivec2(
(floor((fragCoord * inRes) / pixelSize) * pixelSize) + (floor((fragCoord * inRes) / pixelSize) * pixelSize) +
pixelSize / 2.0f pixelSize / 2.0f
@@ -22,5 +24,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(texture, point, 0); fragColor = texelFetch(sampler1, point, 0);
} }

View File

@@ -1,12 +1,14 @@
#version 300 es #version 300 es
precision mediump float; #extension GL_OES_EGL_image_external_essl3 : enable
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 texture; uniform sampler2D sampler1;
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);
@@ -24,7 +26,7 @@ float lanczos(vec2 v)
void main() void main()
{ {
vec2 size = vec2(textureSize(texture, 0)); vec2 size = vec2(textureSize(sampler1, 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);
@@ -54,7 +56,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 += texture2D(texture, uvs[i] * invSize).rgb * factors[i]; color += texture(sampler1, uvs[i] * invSize).rgb * factors[i];
fragColor = vec4(color, 1.0); fragColor = vec4(color, 1.0);
} }

View File

@@ -1,12 +1,14 @@
#version 300 es #version 300 es
precision mediump float; #extension GL_OES_EGL_image_external_essl3 : enable
precision highp float;
in vec2 fragCoord; in vec2 fragCoord;
out vec4 fragColor; out vec4 fragColor;
uniform sampler2D texture; uniform sampler2D sampler1;
void main() void main()
{ {
fragColor = texture2D(texture, fragCoord); fragColor = texture(sampler1, fragCoord);
} }

View File

@@ -1,12 +1,14 @@
#version 300 es #version 300 es
precision mediump float; #extension GL_OES_EGL_image_external_essl3 : enable
precision highp float;
#include "compat.h" #include "compat.h"
in vec2 fragCoord; in vec2 fragCoord;
out vec4 fragColor; out vec4 fragColor;
uniform sampler2D texture; uniform sampler2D sampler1;
uniform uvec4 uConsts[2]; uniform uvec4 uConsts[2];
#define A_GPU 1 #define A_GPU 1
@@ -16,7 +18,7 @@ uniform uvec4 uConsts[2];
vec3 imageLoad(ivec2 point) vec3 imageLoad(ivec2 point)
{ {
return texelFetch(texture, point, 0).rgb; return texelFetch(sampler1, point, 0).rgb;
} }
AF3 CasLoad(ASU2 p) AF3 CasLoad(ASU2 p)
@@ -30,7 +32,7 @@ void CasInput(inout AF1 r,inout AF1 g,inout AF1 b) {}
void main() void main()
{ {
vec2 res = vec2(textureSize(texture, 0)); vec2 res = vec2(textureSize(sampler1, 0));
uvec2 point = uvec2(fragCoord * res); uvec2 point = uvec2(fragCoord * res);
CasFilter( CasFilter(

View File

@@ -1,12 +1,14 @@
#version 300 es #version 300 es
precision mediump float; #extension GL_OES_EGL_image_external_essl3 : enable
precision highp float;
#include "compat.h" #include "compat.h"
in vec2 fragCoord; in vec2 fragCoord;
out vec4 fragColor; out vec4 fragColor;
uniform sampler2D texture; uniform sampler2D sampler1;
uniform vec2 uOutRes; uniform vec2 uOutRes;
uniform uvec4 uConsts[4]; uniform uvec4 uConsts[4];
@@ -18,20 +20,9 @@ uniform uvec4 uConsts[4];
#define FSR_EASU_F 1 #define FSR_EASU_F 1
vec4 _textureGather(sampler2D tex, vec2 uv, int comp) AF4 FsrEasuRF(AF2 p){return AF4(textureGather(sampler1, p, 0));}
{ AF4 FsrEasuGF(AF2 p){return AF4(textureGather(sampler1, p, 1));}
vec2 res = vec2(textureSize(tex, 0)); AF4 FsrEasuBF(AF2 p){return AF4(textureGather(sampler1, p, 2));}
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"

View File

@@ -1,12 +1,12 @@
#version 300 es #version 300 es
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 texture; uniform sampler2D sampler1;
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(texture, ASU2(p), 0); } AF4 FsrRcasLoadF(ASU2 p) { return texelFetch(sampler1, 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(texture, 0)); vec2 inRes = vec2(textureSize(sampler1, 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);

View File

@@ -25,6 +25,7 @@
#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>
@@ -76,6 +77,7 @@ 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;
} }
@@ -203,14 +205,7 @@ 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 EGL_TEX_STATUS_OK; return this->ops.bind(this);
} }

View File

@@ -93,6 +93,9 @@ 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;

View File

@@ -292,6 +292,19 @@ 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,
@@ -299,7 +312,8 @@ 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 =
@@ -309,5 +323,6 @@ 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
}; };

View File

@@ -48,6 +48,7 @@ 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);

View File

@@ -46,12 +46,26 @@ EGL_TextureOps EGL_TextureDMABUF;
// internal functions // internal functions
static void egl_texDMABUFCleanup(TexDMABUF * this) static void egl_texDMABUFCleanup(EGL_Texture * texture)
{ {
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
@@ -92,7 +106,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(this); egl_texDMABUFCleanup(texture);
vector_destroy(&this->images); vector_destroy(&this->images);
egl_texBufferFree(&parent->base); egl_texBufferFree(&parent->base);
@@ -102,11 +116,27 @@ 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(this); egl_texDMABUFCleanup(texture);
return egl_texBufferSetup(&parent->base, setup); glGenTextures(parent->texCount, parent->tex);
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,
@@ -173,8 +203,8 @@ static bool egl_texDMABUFUpdate(EGL_Texture * texture,
INTERLOCKED_SECTION(parent->copyLock, INTERLOCKED_SECTION(parent->copyLock,
{ {
glBindTexture(GL_TEXTURE_2D, parent->tex[parent->bufIndex]); glBindTexture(GL_TEXTURE_EXTERNAL_OES, parent->tex[parent->bufIndex]);
g_egl_dynProcs.glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); g_egl_dynProcs.glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
if (parent->sync) if (parent->sync)
glDeleteSync(parent->sync); glDeleteSync(parent->sync);
@@ -238,6 +268,18 @@ 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,
@@ -245,5 +287,6 @@ 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
}; };

View File

@@ -147,5 +147,6 @@ 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
}; };

View File

@@ -1814,6 +1814,10 @@ 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;

View File

@@ -24,6 +24,7 @@
#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"