mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-21 21:17:19 +00:00
[client] egl: make filters damage aware
This saves a lot of GPU power for partial updates. Running testufo with lanczos downscaling and FSR upscaling consumed over 90 W, but with this commit, consumed only 75 W.
This commit is contained in:
parent
e9bf225c75
commit
1b58f2592c
@ -92,6 +92,7 @@ add_library(renderer_EGL STATIC
|
||||
framebuffer.c
|
||||
postprocess.c
|
||||
ffx.c
|
||||
filter.c
|
||||
filter_ffx_cas.c
|
||||
filter_ffx_fsr1.c
|
||||
filter_downscale.c
|
||||
|
@ -361,9 +361,14 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
|
||||
int scaleAlgo = EGL_SCALE_NEAREST;
|
||||
|
||||
egl_desktopRectsMatrix((float *)desktop->matrix->data,
|
||||
desktop->width, desktop->height, x, y, scaleX, scaleY, rotate);
|
||||
egl_desktopRectsUpdate(desktop->mesh, rects, desktop->width, desktop->height);
|
||||
|
||||
if (atomic_exchange(&desktop->processFrame, false) ||
|
||||
egl_postProcessConfigModified(desktop->pp))
|
||||
egl_postProcessRun(desktop->pp, desktop->texture, outputWidth, outputHeight);
|
||||
egl_postProcessRun(desktop->pp, desktop->texture, desktop->mesh,
|
||||
desktop->width, desktop->height, outputWidth, outputHeight);
|
||||
|
||||
unsigned int finalSizeX, finalSizeY;
|
||||
GLuint texture = egl_postProcessGetOutput(desktop->pp,
|
||||
@ -399,10 +404,6 @@ bool egl_desktopRender(EGL_Desktop * desktop, unsigned int outputWidth,
|
||||
scaleAlgo = desktop->scaleAlgo;
|
||||
}
|
||||
|
||||
egl_desktopRectsMatrix((float *)desktop->matrix->data,
|
||||
desktop->width, desktop->height, x, y, scaleX, scaleY, rotate);
|
||||
egl_desktopRectsUpdate(desktop->mesh, rects, desktop->width, desktop->height);
|
||||
|
||||
const struct DesktopShader * shader = &desktop->shader;
|
||||
EGL_Uniform uniforms[] =
|
||||
{
|
||||
|
30
client/renderers/EGL/filter.c
Normal file
30
client/renderers/EGL/filter.c
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Looking Glass
|
||||
* Copyright © 2017-2021 The Looking Glass Authors
|
||||
* https://looking-glass.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
void egl_filterRectsRender(EGL_Shader * shader, EGL_FilterRects * rects)
|
||||
{
|
||||
glUniformMatrix3x2fv(egl_shaderGetUniform(shader, "transform"),
|
||||
1, GL_FALSE, rects->matrix);
|
||||
glUniform2f(egl_shaderGetUniform(shader, "desktopSize"),
|
||||
rects->width, rects->height);
|
||||
egl_desktopRectsRender(rects->rects);
|
||||
}
|
@ -23,10 +23,19 @@
|
||||
#include "util.h"
|
||||
#include "shader.h"
|
||||
#include "egltypes.h"
|
||||
#include "desktop_rects.h"
|
||||
#include "model.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef struct EGL_FilterRects
|
||||
{
|
||||
EGL_DesktopRects * rects;
|
||||
GLfloat * matrix;
|
||||
int width, height;
|
||||
}
|
||||
EGL_FilterRects;
|
||||
|
||||
typedef struct EGL_Filter EGL_Filter;
|
||||
|
||||
typedef struct EGL_FilterOps
|
||||
@ -78,7 +87,8 @@ typedef struct EGL_FilterOps
|
||||
|
||||
/* runs the filter on the provided texture
|
||||
* returns the processed texture as the output */
|
||||
GLuint (*run)(EGL_Filter * filter, EGL_Model * model, GLuint texture);
|
||||
GLuint (*run)(EGL_Filter * filter, EGL_FilterRects * rects,
|
||||
GLuint texture);
|
||||
|
||||
/* called when the filter output is no loger needed so it can release memory
|
||||
* this is optional */
|
||||
@ -146,10 +156,10 @@ static inline bool egl_filterPrepare(EGL_Filter * filter)
|
||||
return filter->ops.prepare(filter);
|
||||
}
|
||||
|
||||
static inline GLuint egl_filterRun(EGL_Filter * filter, EGL_Model * model,
|
||||
GLuint texture)
|
||||
static inline GLuint egl_filterRun(EGL_Filter * filter,
|
||||
EGL_FilterRects * rects, GLuint texture)
|
||||
{
|
||||
return filter->ops.run(filter, model, texture);
|
||||
return filter->ops.run(filter, rects, texture);
|
||||
}
|
||||
|
||||
static inline void egl_filterRelease(EGL_Filter * filter)
|
||||
@ -157,3 +167,5 @@ static inline void egl_filterRelease(EGL_Filter * filter)
|
||||
if (filter->ops.release)
|
||||
filter->ops.release(filter);
|
||||
}
|
||||
|
||||
void egl_filterRectsRender(EGL_Shader * shader, EGL_FilterRects * rects);
|
||||
|
@ -385,8 +385,8 @@ static bool egl_filterDownscalePrepare(EGL_Filter * filter)
|
||||
return true;
|
||||
}
|
||||
|
||||
static GLuint egl_filterDownscaleRun(EGL_Filter * filter, EGL_Model * model,
|
||||
GLuint texture)
|
||||
static GLuint egl_filterDownscaleRun(EGL_Filter * filter,
|
||||
EGL_FilterRects * rects, GLuint texture)
|
||||
{
|
||||
EGL_FilterDownscale * this = UPCAST(EGL_FilterDownscale, filter);
|
||||
|
||||
@ -395,25 +395,31 @@ static GLuint egl_filterDownscaleRun(EGL_Filter * filter, EGL_Model * model,
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
EGL_Shader * shader;
|
||||
|
||||
switch (this->filter)
|
||||
{
|
||||
case DOWNSCALE_NEAREST:
|
||||
glBindSampler(0, this->sampler[0]);
|
||||
egl_shaderUse(this->nearest);
|
||||
shader = this->nearest;
|
||||
break;
|
||||
|
||||
case DOWNSCALE_LINEAR:
|
||||
glBindSampler(0, this->sampler[1]);
|
||||
egl_shaderUse(this->linear);
|
||||
shader = this->linear;
|
||||
break;
|
||||
|
||||
case DOWNSCALE_LANCZOS2:
|
||||
glBindSampler(0, this->sampler[0]);
|
||||
egl_shaderUse(this->lanczos2);
|
||||
shader = this->lanczos2;
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG_UNREACHABLE();
|
||||
}
|
||||
|
||||
egl_modelRender(model);
|
||||
egl_shaderUse(shader);
|
||||
egl_filterRectsRender(shader, rects);
|
||||
|
||||
return egl_framebufferGetTexture(this->fb);
|
||||
}
|
||||
|
@ -262,8 +262,8 @@ static bool egl_filterFFXCASPrepare(EGL_Filter * filter)
|
||||
return true;
|
||||
}
|
||||
|
||||
static GLuint egl_filterFFXCASRun(EGL_Filter * filter, EGL_Model * model,
|
||||
GLuint texture)
|
||||
static GLuint egl_filterFFXCASRun(EGL_Filter * filter,
|
||||
EGL_FilterRects * rects, GLuint texture)
|
||||
{
|
||||
EGL_FilterFFXCAS * this = UPCAST(EGL_FilterFFXCAS, filter);
|
||||
|
||||
@ -274,7 +274,7 @@ static GLuint egl_filterFFXCASRun(EGL_Filter * filter, EGL_Model * model,
|
||||
glBindSampler(0, this->sampler);
|
||||
|
||||
egl_shaderUse(this->shader);
|
||||
egl_modelRender(model);
|
||||
egl_filterRectsRender(this->shader, rects);
|
||||
|
||||
return egl_framebufferGetTexture(this->fb);
|
||||
}
|
||||
|
@ -388,8 +388,8 @@ static bool egl_filterFFXFSR1Prepare(EGL_Filter * filter)
|
||||
return true;
|
||||
}
|
||||
|
||||
static GLuint egl_filterFFXFSR1Run(EGL_Filter * filter, EGL_Model * model,
|
||||
GLuint texture)
|
||||
static GLuint egl_filterFFXFSR1Run(EGL_Filter * filter,
|
||||
EGL_FilterRects * rects, GLuint texture)
|
||||
{
|
||||
EGL_FilterFFXFSR1 * this = UPCAST(EGL_FilterFFXFSR1, filter);
|
||||
|
||||
@ -399,7 +399,7 @@ static GLuint egl_filterFFXFSR1Run(EGL_Filter * filter, EGL_Model * model,
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glBindSampler(0, this->sampler);
|
||||
egl_shaderUse(this->easu);
|
||||
egl_modelRender(model);
|
||||
egl_filterRectsRender(this->easu, rects);
|
||||
texture = egl_framebufferGetTexture(this->easuFb);
|
||||
|
||||
// pass 2, Rcas
|
||||
@ -408,7 +408,7 @@ static GLuint egl_filterFFXFSR1Run(EGL_Filter * filter, EGL_Model * model,
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glBindSampler(0, this->sampler);
|
||||
egl_shaderUse(this->rcas);
|
||||
egl_modelRender(model);
|
||||
egl_filterRectsRender(this->rcas, rects);
|
||||
texture = egl_framebufferGetTexture(this->rcasFb);
|
||||
|
||||
return texture;
|
||||
|
@ -53,7 +53,7 @@ struct EGL_PostProcess
|
||||
unsigned int outputX, outputY;
|
||||
_Atomic(bool) modified;
|
||||
|
||||
EGL_Model * model;
|
||||
EGL_DesktopRects * rects;
|
||||
|
||||
StringList presets;
|
||||
char * presetDir;
|
||||
@ -523,12 +523,11 @@ bool egl_postProcessInit(EGL_PostProcess ** pp)
|
||||
goto error_this;
|
||||
}
|
||||
|
||||
if (!egl_modelInit(&this->model))
|
||||
if (!egl_desktopRectsInit(&this->rects, 1))
|
||||
{
|
||||
DEBUG_ERROR("Failed to initialize the model");
|
||||
DEBUG_ERROR("Failed to initialize the desktop rects");
|
||||
goto error_filters;
|
||||
}
|
||||
egl_modelSetDefault(this->model, false);
|
||||
|
||||
loadPresetList(this);
|
||||
reorderFilters(this);
|
||||
@ -561,7 +560,7 @@ void egl_postProcessFree(EGL_PostProcess ** pp)
|
||||
if (this->presets)
|
||||
stringlist_free(&this->presets);
|
||||
|
||||
egl_modelFree(&this->model);
|
||||
egl_desktopRectsFree(&this->rects);
|
||||
free(this->presetError);
|
||||
free(this);
|
||||
*pp = NULL;
|
||||
@ -583,6 +582,7 @@ bool egl_postProcessConfigModified(EGL_PostProcess * this)
|
||||
}
|
||||
|
||||
bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
||||
EGL_DesktopRects * rects, int desktopWidth, int desktopHeight,
|
||||
unsigned int targetX, unsigned int targetY)
|
||||
{
|
||||
EGL_Filter * lastFilter = NULL;
|
||||
@ -592,7 +592,22 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
||||
if (egl_textureGet(tex, &texture, &sizeX, &sizeY) != EGL_TEX_STATUS_OK)
|
||||
return false;
|
||||
|
||||
atomic_store(&this->modified, false);
|
||||
if (atomic_exchange(&this->modified, false))
|
||||
{
|
||||
rects = this->rects;
|
||||
egl_desktopRectsUpdate(rects, NULL, desktopWidth, desktopHeight);
|
||||
}
|
||||
|
||||
GLfloat matrix[6];
|
||||
egl_desktopRectsMatrix(matrix, desktopWidth, desktopHeight, 0.0f, 0.0f,
|
||||
1.0f, 1.0f, LG_ROTATE_0);
|
||||
|
||||
EGL_FilterRects filterRects = {
|
||||
.rects = rects,
|
||||
.matrix = matrix,
|
||||
.width = desktopWidth,
|
||||
.height = desktopHeight,
|
||||
};
|
||||
|
||||
EGL_Filter * filter;
|
||||
vector_forEach(filter, &this->filters)
|
||||
@ -603,7 +618,7 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
||||
if (!egl_filterPrepare(filter))
|
||||
continue;
|
||||
|
||||
texture = egl_filterRun(filter, this->model, texture);
|
||||
texture = egl_filterRun(filter, &filterRects, texture);
|
||||
egl_filterGetOutputRes(filter, &sizeX, &sizeY);
|
||||
|
||||
if (lastFilter)
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "desktop_rects.h"
|
||||
#include "filter.h"
|
||||
#include "texture.h"
|
||||
|
||||
@ -39,6 +40,7 @@ bool egl_postProcessConfigModified(EGL_PostProcess * this);
|
||||
/* apply the filters to the supplied texture
|
||||
* targetX/Y is the final target output dimension hint if scalers are present */
|
||||
bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
||||
EGL_DesktopRects * rects, int desktopWidth, int desktopHeight,
|
||||
unsigned int targetX, unsigned int targetY);
|
||||
|
||||
GLuint egl_postProcessGetOutput(EGL_PostProcess * this,
|
||||
|
@ -1,14 +1,15 @@
|
||||
#version 300 es
|
||||
|
||||
precision mediump float;
|
||||
|
||||
layout(location = 0) in vec2 uVertex;
|
||||
layout(location = 1) in vec2 uUV;
|
||||
|
||||
layout(location = 0) in vec2 vertex;
|
||||
out vec2 fragCoord;
|
||||
|
||||
uniform vec2 desktopSize;
|
||||
uniform mat3x2 transform;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(uVertex, 0.0, 1.0);
|
||||
fragCoord = uUV;
|
||||
vec2 pos = transform * vec3(vertex, 1.0);
|
||||
gl_Position = vec4(pos.x, -pos.y, 0.0, 1.0);
|
||||
fragCoord = vertex / desktopSize;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user