mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-07-21 06:42:02 +00:00
[client] egl: cache post-process configuration
Build the active filter chain only when its configuration changes, including filter settings or order, input format, dimensions, output size, and DMA mode. Unchanged frames now execute only the cached active filters, avoiding repeated setup, preparation, and output-resolution queries. Reconfiguration forces a full-frame pass to prevent stale intermediate framebuffer contents. Also refresh CAS and FSR uniforms when loading presets and move downscale pass selection out of the per-frame path.
This commit is contained in:
@@ -68,14 +68,14 @@ 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
|
/* configure the input format of the filter when the chain changes
|
||||||
* useDMA will be true if the texture provided needs to use samplerExternalOES
|
* 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,
|
||||||
unsigned int desktopWidth, unsigned int desktopHeight, bool useDMA);
|
unsigned int desktopWidth, unsigned int desktopHeight, bool useDMA);
|
||||||
|
|
||||||
/* set the output resolution hint for the filter
|
/* set the output resolution hint while configuring the chain
|
||||||
* this is optional and only a hint */
|
* this is optional and only a hint */
|
||||||
void (*setOutputResHint)(EGL_Filter * filter,
|
void (*setOutputResHint)(EGL_Filter * filter,
|
||||||
unsigned int x, unsigned int y);
|
unsigned int x, unsigned int y);
|
||||||
@@ -84,7 +84,7 @@ typedef struct EGL_FilterOps
|
|||||||
void (*getOutputRes)(EGL_Filter * filter,
|
void (*getOutputRes)(EGL_Filter * filter,
|
||||||
unsigned int *x, unsigned int *y, enum EGL_PixelFormat *pixFmt);
|
unsigned int *x, unsigned int *y, enum EGL_PixelFormat *pixFmt);
|
||||||
|
|
||||||
/* prepare the shader for use
|
/* finalize the filter while configuring the chain
|
||||||
* A filter can return false to bypass it */
|
* A filter can return false to bypass it */
|
||||||
bool (*prepare)(EGL_Filter * filter);
|
bool (*prepare)(EGL_Filter * filter);
|
||||||
|
|
||||||
|
|||||||
@@ -379,32 +379,13 @@ static bool egl_filterDownscalePrepare(EGL_Filter * filter)
|
|||||||
if (this->prepared)
|
if (this->prepared)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
EGL_Shader * shader;
|
||||||
|
GLenum sampling;
|
||||||
switch (this->filter)
|
switch (this->filter)
|
||||||
{
|
{
|
||||||
case DOWNSCALE_NEAREST:
|
case DOWNSCALE_NEAREST:
|
||||||
egl_uniform3f(this->uNearest, this->pixelSize,
|
egl_uniform3f(this->uNearest, this->pixelSize,
|
||||||
this->vOffset, this->hOffset);
|
this->vOffset, this->hOffset);
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this->prepared = true;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static EGL_Texture * egl_filterDownscaleRun(EGL_Filter * filter,
|
|
||||||
EGL_FilterRects * rects, EGL_Texture * texture)
|
|
||||||
{
|
|
||||||
EGL_FilterDownscale * this = UPCAST(EGL_FilterDownscale, filter);
|
|
||||||
|
|
||||||
EGL_Shader * shader;
|
|
||||||
GLenum sampling;
|
|
||||||
|
|
||||||
switch (this->filter)
|
|
||||||
{
|
|
||||||
case DOWNSCALE_NEAREST:
|
|
||||||
shader = this->nearest;
|
shader = this->nearest;
|
||||||
sampling = GL_NEAREST;
|
sampling = GL_NEAREST;
|
||||||
break;
|
break;
|
||||||
@@ -425,6 +406,15 @@ static EGL_Texture * egl_filterDownscaleRun(EGL_Filter * filter,
|
|||||||
|
|
||||||
egl_effectPassSetShader(this->pass, shader);
|
egl_effectPassSetShader(this->pass, shader);
|
||||||
egl_effectPassSetFilter(this->pass, sampling, sampling);
|
egl_effectPassSetFilter(this->pass, sampling, sampling);
|
||||||
|
this->prepared = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static EGL_Texture * egl_filterDownscaleRun(EGL_Filter * filter,
|
||||||
|
EGL_FilterRects * rects, EGL_Texture * texture)
|
||||||
|
{
|
||||||
|
EGL_FilterDownscale * this = UPCAST(EGL_FilterDownscale, filter);
|
||||||
return egl_effectRun(this->effect, rects, texture);
|
return egl_effectRun(this->effect, rects, texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ static void egl_filterFFXCASEarlyInit(void)
|
|||||||
|
|
||||||
static void casUpdateConsts(EGL_FilterFFXCAS * this)
|
static void casUpdateConsts(EGL_FilterFFXCAS * this)
|
||||||
{
|
{
|
||||||
|
if (!this->width || !this->height)
|
||||||
|
return;
|
||||||
|
|
||||||
ffxCasConst((uint32_t *)this->consts, this->sharpness,
|
ffxCasConst((uint32_t *)this->consts, this->sharpness,
|
||||||
this->width, this->height,
|
this->width, this->height,
|
||||||
this->width, this->height);
|
this->width, this->height);
|
||||||
@@ -96,6 +99,8 @@ static void egl_filterFFXCASLoadState(EGL_Filter * filter)
|
|||||||
|
|
||||||
this->enable = option_get_bool ("eglFilter", "ffxCAS");
|
this->enable = option_get_bool ("eglFilter", "ffxCAS");
|
||||||
this->sharpness = option_get_float("eglFilter", "ffxCASSharpness");
|
this->sharpness = option_get_float("eglFilter", "ffxCASSharpness");
|
||||||
|
casUpdateConsts(this);
|
||||||
|
this->prepared = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool egl_filterFFXCASInit(EGL_Filter ** filter)
|
static bool egl_filterFFXCASInit(EGL_Filter ** filter)
|
||||||
|
|||||||
@@ -101,6 +101,8 @@ static void egl_filterFFXFSR1LoadState(EGL_Filter * filter)
|
|||||||
|
|
||||||
this->enable = option_get_bool ("eglFilter", "ffxFSR");
|
this->enable = option_get_bool ("eglFilter", "ffxFSR");
|
||||||
this->sharpness = option_get_float("eglFilter", "ffxFSRSharpness");
|
this->sharpness = option_get_float("eglFilter", "ffxFSRSharpness");
|
||||||
|
rcasUpdateUniform(this);
|
||||||
|
this->prepared = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool egl_filterFFXFSR1Init(EGL_Filter ** filter)
|
static bool egl_filterFFXFSR1Init(EGL_Filter ** filter)
|
||||||
@@ -159,7 +161,6 @@ static bool egl_filterFFXFSR1Init(EGL_Filter ** filter)
|
|||||||
this->uRcasConsts = egl_shaderGetUniform(this->rcas, "uConsts");
|
this->uRcasConsts = egl_shaderGetUniform(this->rcas, "uConsts");
|
||||||
|
|
||||||
egl_filterFFXFSR1LoadState(&this->base);
|
egl_filterFFXFSR1LoadState(&this->base);
|
||||||
rcasUpdateUniform(this);
|
|
||||||
|
|
||||||
*filter = &this->base;
|
*filter = &this->base;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -48,12 +48,25 @@ static const EGL_FilterOps * EGL_Filters[] =
|
|||||||
|
|
||||||
struct EGL_PostProcess
|
struct EGL_PostProcess
|
||||||
{
|
{
|
||||||
Vector filters, internalFilters;
|
Vector filters, internalFilters, activeFilters;
|
||||||
EGL_Texture * output;
|
EGL_Texture * output;
|
||||||
unsigned int outputX, outputY;
|
unsigned int outputX, outputY;
|
||||||
_Atomic(bool) modified;
|
_Atomic(bool) modified;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
bool valid;
|
||||||
|
EGL_PixelFormat pixFmt;
|
||||||
|
unsigned int inputX, inputY;
|
||||||
|
int desktopWidth, desktopHeight;
|
||||||
|
unsigned int targetX, targetY;
|
||||||
|
bool useDMA;
|
||||||
|
unsigned int outputX, outputY;
|
||||||
|
}
|
||||||
|
config;
|
||||||
|
|
||||||
EGL_DesktopRects * rects;
|
EGL_DesktopRects * rects;
|
||||||
|
GLfloat matrix[6];
|
||||||
|
|
||||||
StringList presets;
|
StringList presets;
|
||||||
char * presetDir;
|
char * presetDir;
|
||||||
@@ -256,6 +269,13 @@ static void reorderFilters(struct EGL_PostProcess * this)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!*orderStr)
|
||||||
|
{
|
||||||
|
stringlist_free(&order);
|
||||||
|
free(orderStr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char * p = orderStr;
|
char * p = orderStr;
|
||||||
while (*p)
|
while (*p)
|
||||||
{
|
{
|
||||||
@@ -515,7 +535,7 @@ static void configUI(void * opaque, int * id)
|
|||||||
igSetTooltip(filters[moveIdx]->ops.name);
|
igSetTooltip(filters[moveIdx]->ops.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doMove)
|
if (doMove && mouseIdx != moveIdx)
|
||||||
{
|
{
|
||||||
EGL_Filter * tmp = filters[moveIdx];
|
EGL_Filter * tmp = filters[moveIdx];
|
||||||
if (mouseIdx > moveIdx) // moving down
|
if (mouseIdx > moveIdx) // moving down
|
||||||
@@ -530,11 +550,12 @@ static void configUI(void * opaque, int * id)
|
|||||||
(moveIdx - mouseIdx) * sizeof(EGL_Filter *));
|
(moveIdx - mouseIdx) * sizeof(EGL_Filter *));
|
||||||
|
|
||||||
filters[mouseIdx] = tmp;
|
filters[mouseIdx] = tmp;
|
||||||
|
redraw = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (redraw)
|
if (redraw)
|
||||||
{
|
{
|
||||||
atomic_store(&this->modified, true);
|
egl_postProcessInvalidate(this);
|
||||||
app_invalidateWindow(true);
|
app_invalidateWindow(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -547,6 +568,7 @@ bool egl_postProcessInit(EGL_PostProcess ** pp)
|
|||||||
DEBUG_ERROR("Failed to allocate memory");
|
DEBUG_ERROR("Failed to allocate memory");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
atomic_init(&this->modified, false);
|
||||||
|
|
||||||
if (!vector_create(&this->filters,
|
if (!vector_create(&this->filters,
|
||||||
sizeof(EGL_Filter *), ARRAY_LENGTH(EGL_Filters)))
|
sizeof(EGL_Filter *), ARRAY_LENGTH(EGL_Filters)))
|
||||||
@@ -562,10 +584,17 @@ bool egl_postProcessInit(EGL_PostProcess ** pp)
|
|||||||
goto error_filters;
|
goto error_filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!vector_create(&this->activeFilters,
|
||||||
|
sizeof(EGL_Filter *), ARRAY_LENGTH(EGL_Filters) + 1))
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("Failed to allocate the active filter list");
|
||||||
|
goto error_internal;
|
||||||
|
}
|
||||||
|
|
||||||
if (!egl_desktopRectsInit(&this->rects, 1))
|
if (!egl_desktopRectsInit(&this->rects, 1))
|
||||||
{
|
{
|
||||||
DEBUG_ERROR("Failed to initialize the desktop rects");
|
DEBUG_ERROR("Failed to initialize the desktop rects");
|
||||||
goto error_internal;
|
goto error_active;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadPresetList(this);
|
loadPresetList(this);
|
||||||
@@ -575,6 +604,9 @@ bool egl_postProcessInit(EGL_PostProcess ** pp)
|
|||||||
*pp = this;
|
*pp = this;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
error_active:
|
||||||
|
vector_destroy(&this->activeFilters);
|
||||||
|
|
||||||
error_internal:
|
error_internal:
|
||||||
vector_destroy(&this->internalFilters);
|
vector_destroy(&this->internalFilters);
|
||||||
|
|
||||||
@@ -593,6 +625,8 @@ void egl_postProcessFree(EGL_PostProcess ** pp)
|
|||||||
|
|
||||||
EGL_PostProcess * this = *pp;
|
EGL_PostProcess * this = *pp;
|
||||||
|
|
||||||
|
vector_destroy(&this->activeFilters);
|
||||||
|
|
||||||
EGL_Filter ** filter;
|
EGL_Filter ** filter;
|
||||||
vector_forEachRef(filter, &this->filters)
|
vector_forEachRef(filter, &this->filters)
|
||||||
egl_filterFree(filter);
|
egl_filterFree(filter);
|
||||||
@@ -618,55 +652,62 @@ bool egl_postProcessAdd(EGL_PostProcess * this, const EGL_FilterOps * ops)
|
|||||||
if (!egl_filterInit(ops, &filter))
|
if (!egl_filterInit(ops, &filter))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (ops->type == EGL_FILTER_TYPE_INTERNAL)
|
Vector * filters = ops->type == EGL_FILTER_TYPE_INTERNAL ?
|
||||||
vector_push(&this->internalFilters, &filter);
|
&this->internalFilters : &this->filters;
|
||||||
else
|
if (!vector_push(filters, &filter))
|
||||||
vector_push(&this->filters, &filter);
|
{
|
||||||
|
egl_filterFree(&filter);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ops->type != EGL_FILTER_TYPE_INTERNAL)
|
||||||
|
reorderFilters(this);
|
||||||
|
|
||||||
|
egl_postProcessInvalidate(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void egl_postProcessInvalidate(EGL_PostProcess * this)
|
||||||
|
{
|
||||||
|
atomic_store_explicit(&this->modified, true, memory_order_release);
|
||||||
|
}
|
||||||
|
|
||||||
bool egl_postProcessConfigModified(EGL_PostProcess * this)
|
bool egl_postProcessConfigModified(EGL_PostProcess * this)
|
||||||
{
|
{
|
||||||
return atomic_load(&this->modified);
|
return atomic_load_explicit(&this->modified, memory_order_acquire);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
static bool configMatches(EGL_PostProcess * this, EGL_PixelFormat pixFmt,
|
||||||
EGL_DesktopRects * rects, int desktopWidth, int desktopHeight,
|
unsigned int inputX, unsigned int inputY,
|
||||||
|
int desktopWidth, int desktopHeight,
|
||||||
unsigned int targetX, unsigned int targetY, bool useDMA)
|
unsigned int targetX, unsigned int targetY, bool useDMA)
|
||||||
{
|
{
|
||||||
if (targetX == 0 && targetY == 0)
|
return
|
||||||
DEBUG_FATAL("targetX || targetY == 0");
|
this->config.valid &&
|
||||||
|
this->config.pixFmt == pixFmt &&
|
||||||
|
this->config.inputX == inputX &&
|
||||||
|
this->config.inputY == inputY &&
|
||||||
|
this->config.desktopWidth == desktopWidth &&
|
||||||
|
this->config.desktopHeight == desktopHeight &&
|
||||||
|
this->config.targetX == targetX &&
|
||||||
|
this->config.targetY == targetY &&
|
||||||
|
this->config.useDMA == useDMA;
|
||||||
|
}
|
||||||
|
|
||||||
EGL_Filter * lastFilter = NULL;
|
static bool configureChain(EGL_PostProcess * this, EGL_PixelFormat pixFmt,
|
||||||
unsigned int sizeX, sizeY;
|
unsigned int inputX, unsigned int inputY,
|
||||||
|
int desktopWidth, int desktopHeight,
|
||||||
|
unsigned int targetX, unsigned int targetY, bool useDMA)
|
||||||
|
{
|
||||||
|
this->config.valid = false;
|
||||||
|
vector_clear(&this->activeFilters);
|
||||||
|
|
||||||
//TODO: clean this up
|
unsigned int outputX = inputX;
|
||||||
GLuint _unused;
|
unsigned int outputY = inputY;
|
||||||
EGL_PixelFormat pixFmt;
|
EGL_PixelFormat outputFormat = pixFmt;
|
||||||
if (egl_textureGet(tex, &_unused,
|
bool inputDMA = useDMA;
|
||||||
&sizeX, &sizeY, &pixFmt) != EGL_TEX_STATUS_OK)
|
|
||||||
return 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;
|
EGL_Filter * filter;
|
||||||
EGL_Texture * texture = tex;
|
|
||||||
|
|
||||||
const Vector * lists[] =
|
const Vector * lists[] =
|
||||||
{
|
{
|
||||||
&this->internalFilters,
|
&this->internalFilters,
|
||||||
@@ -679,26 +720,108 @@ bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
|||||||
{
|
{
|
||||||
egl_filterSetOutputResHint(filter, targetX, targetY);
|
egl_filterSetOutputResHint(filter, targetX, targetY);
|
||||||
|
|
||||||
if (!egl_filterSetup(filter, pixFmt, sizeX, sizeY,
|
if (!egl_filterSetup(filter, outputFormat, outputX, outputY,
|
||||||
desktopWidth, desktopHeight, useDMA) ||
|
desktopWidth, desktopHeight, inputDMA) ||
|
||||||
!egl_filterPrepare(filter))
|
!egl_filterPrepare(filter))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (!vector_push(&this->activeFilters, &filter))
|
||||||
|
{
|
||||||
|
vector_clear(&this->activeFilters);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
egl_filterGetOutputRes(filter, &outputX, &outputY, &outputFormat);
|
||||||
|
|
||||||
|
/* The first active filter converts external DMA textures into a normal
|
||||||
|
* texture for every subsequent filter. */
|
||||||
|
inputDMA = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
egl_desktopRectsMatrix(this->matrix,
|
||||||
|
desktopWidth, desktopHeight, 0.0f, 0.0f, 1.0f, 1.0f, LG_ROTATE_0);
|
||||||
|
|
||||||
|
this->config.pixFmt = pixFmt;
|
||||||
|
this->config.inputX = inputX;
|
||||||
|
this->config.inputY = inputY;
|
||||||
|
this->config.desktopWidth = desktopWidth;
|
||||||
|
this->config.desktopHeight = desktopHeight;
|
||||||
|
this->config.targetX = targetX;
|
||||||
|
this->config.targetY = targetY;
|
||||||
|
this->config.useDMA = useDMA;
|
||||||
|
this->config.outputX = outputX;
|
||||||
|
this->config.outputY = outputY;
|
||||||
|
this->config.valid = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool egl_postProcessRun(EGL_PostProcess * this, EGL_Texture * tex,
|
||||||
|
EGL_DesktopRects * rects, int desktopWidth, int desktopHeight,
|
||||||
|
unsigned int targetX, unsigned int targetY, bool useDMA)
|
||||||
|
{
|
||||||
|
if (targetX == 0 && targetY == 0)
|
||||||
|
DEBUG_FATAL("targetX || targetY == 0");
|
||||||
|
|
||||||
|
unsigned int inputX, inputY;
|
||||||
|
GLuint _unused;
|
||||||
|
EGL_PixelFormat pixFmt;
|
||||||
|
if (egl_textureGet(tex, &_unused,
|
||||||
|
&inputX, &inputY, &pixFmt) != EGL_TEX_STATUS_OK)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const bool modified =
|
||||||
|
atomic_load_explicit(&this->modified, memory_order_acquire);
|
||||||
|
const bool reconfigure = modified ||
|
||||||
|
!configMatches(this, pixFmt, inputX, inputY,
|
||||||
|
desktopWidth, desktopHeight, targetX, targetY, useDMA);
|
||||||
|
|
||||||
|
if (reconfigure)
|
||||||
|
{
|
||||||
|
if (modified)
|
||||||
|
atomic_exchange_explicit(
|
||||||
|
&this->modified, false, memory_order_acq_rel);
|
||||||
|
|
||||||
|
if (!configureChain(this, pixFmt, inputX, inputY,
|
||||||
|
desktopWidth, desktopHeight, targetX, targetY, useDMA))
|
||||||
|
{
|
||||||
|
egl_postProcessInvalidate(this);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
rects = this->rects;
|
||||||
|
egl_desktopRectsUpdate(rects, NULL, desktopWidth, desktopHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
EGL_FilterRects filterRects = {
|
||||||
|
.rects = rects,
|
||||||
|
.matrix = this->matrix,
|
||||||
|
.width = desktopWidth,
|
||||||
|
.height = desktopHeight,
|
||||||
|
};
|
||||||
|
|
||||||
|
EGL_Texture * texture = tex;
|
||||||
|
EGL_Filter * filter;
|
||||||
|
EGL_Filter * lastFilter = NULL;
|
||||||
|
vector_forEach(filter, &this->activeFilters)
|
||||||
|
{
|
||||||
texture = egl_filterRun(filter, &filterRects, texture);
|
texture = egl_filterRun(filter, &filterRects, texture);
|
||||||
egl_filterGetOutputRes(filter, &sizeX, &sizeY, &pixFmt);
|
if (!texture)
|
||||||
|
{
|
||||||
|
DEBUG_ERROR("EGL filter '%s' failed", filter->ops.id);
|
||||||
|
this->output = NULL;
|
||||||
|
egl_postProcessInvalidate(this);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (lastFilter)
|
if (lastFilter)
|
||||||
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;
|
||||||
this->outputX = sizeX;
|
this->outputX = this->config.outputX;
|
||||||
this->outputY = sizeY;
|
this->outputY = this->config.outputY;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ void egl_postProcessFree(EGL_PostProcess ** pp);
|
|||||||
/* create and add a filter to this processor */
|
/* create and add a filter to this processor */
|
||||||
bool egl_postProcessAdd(EGL_PostProcess * this, const EGL_FilterOps * ops);
|
bool egl_postProcessAdd(EGL_PostProcess * this, const EGL_FilterOps * ops);
|
||||||
|
|
||||||
|
/* mark the filter chain for rebuilding before its next run */
|
||||||
|
void egl_postProcessInvalidate(EGL_PostProcess * this);
|
||||||
|
|
||||||
/* returns true if the configuration was modified since the last run */
|
/* returns true if the configuration was modified since the last run */
|
||||||
bool egl_postProcessConfigModified(EGL_PostProcess * this);
|
bool egl_postProcessConfigModified(EGL_PostProcess * this);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user