mirror of
https://github.com/libretro/RetroArch
synced 2025-02-21 18:40:09 +00:00
Add special point scaler for optimal speed.
This commit is contained in:
parent
3f613882a3
commit
41359681c3
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
|
#include "scaler_int.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -57,6 +58,8 @@ static bool gen_filter_point(struct scaler_ctx *ctx)
|
|||||||
gen_filter_point_sub(&ctx->horiz, ctx->out_width, x_pos, x_step);
|
gen_filter_point_sub(&ctx->horiz, ctx->out_width, x_pos, x_step);
|
||||||
gen_filter_point_sub(&ctx->vert, ctx->out_height, y_pos, y_step);
|
gen_filter_point_sub(&ctx->vert, ctx->out_height, y_pos, y_step);
|
||||||
|
|
||||||
|
ctx->scaler_special = scaler_argb8888_point_special;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,6 +139,8 @@ bool scaler_ctx_gen_filter(struct scaler_ctx *ctx)
|
|||||||
ctx->unscaled = false;
|
ctx->unscaled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx->scaler_special = NULL;
|
||||||
|
|
||||||
if (!allocate_frames(ctx))
|
if (!allocate_frames(ctx))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -192,13 +194,50 @@ void scaler_ctx_scale(struct scaler_ctx *ctx,
|
|||||||
clock_gettime(CLOCK_MONOTONIC, &start_tv);
|
clock_gettime(CLOCK_MONOTONIC, &start_tv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ctx->unscaled)
|
if (ctx->unscaled) // Just perform straight pixel conversion.
|
||||||
{
|
{
|
||||||
ctx->direct_pixconv(output, input,
|
ctx->direct_pixconv(output, input,
|
||||||
ctx->out_width, ctx->out_height,
|
ctx->out_width, ctx->out_height,
|
||||||
ctx->out_stride, ctx->in_stride);
|
ctx->out_stride, ctx->in_stride);
|
||||||
}
|
}
|
||||||
else
|
else if (ctx->scaler_special) // Take some special, and (hopefully) more optimized path.
|
||||||
|
{
|
||||||
|
const void *inp = input;
|
||||||
|
int in_stride = ctx->in_stride;
|
||||||
|
|
||||||
|
if (ctx->in_fmt != SCALER_FMT_ARGB8888)
|
||||||
|
{
|
||||||
|
ctx->in_pixconv(ctx->input.frame, input,
|
||||||
|
ctx->in_width, ctx->in_height,
|
||||||
|
ctx->input.stride, ctx->in_stride);
|
||||||
|
|
||||||
|
inp = ctx->input.frame;
|
||||||
|
in_stride = ctx->input.stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool conv_out = ctx->out_fmt != SCALER_FMT_ARGB8888;
|
||||||
|
void *outp = output;
|
||||||
|
int out_stride = ctx->out_stride;
|
||||||
|
|
||||||
|
if (conv_out)
|
||||||
|
{
|
||||||
|
outp = ctx->output.frame;
|
||||||
|
out_stride = ctx->output.stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->scaler_special(ctx, outp, inp,
|
||||||
|
ctx->out_width, ctx->out_height,
|
||||||
|
ctx->in_width, ctx->in_height,
|
||||||
|
out_stride, in_stride);
|
||||||
|
|
||||||
|
if (conv_out)
|
||||||
|
{
|
||||||
|
ctx->out_pixconv(output, ctx->output.frame,
|
||||||
|
ctx->out_width, ctx->out_height,
|
||||||
|
ctx->out_stride, ctx->output.stride);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Take generic filter path.
|
||||||
{
|
{
|
||||||
if (ctx->in_fmt != SCALER_FMT_ARGB8888)
|
if (ctx->in_fmt != SCALER_FMT_ARGB8888)
|
||||||
{
|
{
|
||||||
@ -230,4 +269,3 @@ void scaler_ctx_scale(struct scaler_ctx *ctx,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,6 +63,8 @@ struct scaler_ctx
|
|||||||
const void*, int);
|
const void*, int);
|
||||||
void (*scaler_vert)(const struct scaler_ctx*,
|
void (*scaler_vert)(const struct scaler_ctx*,
|
||||||
void*, int);
|
void*, int);
|
||||||
|
void (*scaler_special)(const struct scaler_ctx*,
|
||||||
|
void*, const void*, int, int, int, int, int, int);
|
||||||
|
|
||||||
void (*in_pixconv)(void*, const void*, int, int, int, int);
|
void (*in_pixconv)(void*, const void*, int, int, int, int);
|
||||||
void (*out_pixconv)(void*, const void*, int, int, int, int);
|
void (*out_pixconv)(void*, const void*, int, int, int, int);
|
||||||
|
@ -231,3 +231,33 @@ void scaler_argb8888_horiz(const struct scaler_ctx *ctx, const void *input_, int
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void scaler_argb8888_point_special(const struct scaler_ctx *ctx,
|
||||||
|
void *output_, const void *input_,
|
||||||
|
int out_width, int out_height,
|
||||||
|
int in_width, int in_height,
|
||||||
|
int out_stride, int in_stride)
|
||||||
|
{
|
||||||
|
(void)ctx;
|
||||||
|
int x_pos = (1 << 15) * in_width / out_width - (1 << 15);
|
||||||
|
int x_step = (1 << 16) * in_width / out_width;
|
||||||
|
int y_pos = (1 << 15) * in_height / out_height - (1 << 15);
|
||||||
|
int y_step = (1 << 16) * in_height / out_height;
|
||||||
|
|
||||||
|
if (x_pos < 0)
|
||||||
|
x_pos = 0;
|
||||||
|
if (y_pos < 0)
|
||||||
|
y_pos = 0;
|
||||||
|
|
||||||
|
const uint32_t *input = (const uint32_t*)input_;
|
||||||
|
uint32_t *output = (uint32_t*)output_;
|
||||||
|
|
||||||
|
for (int h = 0; h < out_height; h++, y_pos += y_step, output += out_stride >> 2)
|
||||||
|
{
|
||||||
|
int x = x_pos;
|
||||||
|
const uint32_t *inp = input + (y_pos >> 16) * (in_stride >> 2);
|
||||||
|
|
||||||
|
for (int w = 0; w < out_width; w++, x += x_step)
|
||||||
|
output[w] = inp[x >> 16];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -21,5 +21,11 @@
|
|||||||
void scaler_argb8888_vert(const struct scaler_ctx *ctx, void *output, int stride);
|
void scaler_argb8888_vert(const struct scaler_ctx *ctx, void *output, int stride);
|
||||||
void scaler_argb8888_horiz(const struct scaler_ctx *ctx, const void *input, int stride);
|
void scaler_argb8888_horiz(const struct scaler_ctx *ctx, const void *input, int stride);
|
||||||
|
|
||||||
|
void scaler_argb8888_point_special(const struct scaler_ctx *ctx,
|
||||||
|
void *output, const void *input,
|
||||||
|
int out_width, int out_height,
|
||||||
|
int in_width, int in_height,
|
||||||
|
int out_stride, int in_stride);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user