Add special point scaler for optimal speed.

This commit is contained in:
Themaister 2012-09-03 00:48:00 +02:00
parent 3f613882a3
commit 41359681c3
5 changed files with 82 additions and 3 deletions

View File

@ -15,6 +15,7 @@
#include "filter.h"
#include "scaler_int.h"
#include <math.h>
#include <stdio.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->vert, ctx->out_height, y_pos, y_step);
ctx->scaler_special = scaler_argb8888_point_special;
return true;
}

View File

@ -139,6 +139,8 @@ bool scaler_ctx_gen_filter(struct scaler_ctx *ctx)
ctx->unscaled = false;
}
ctx->scaler_special = NULL;
if (!allocate_frames(ctx))
return false;
@ -192,13 +194,50 @@ void scaler_ctx_scale(struct scaler_ctx *ctx,
clock_gettime(CLOCK_MONOTONIC, &start_tv);
#endif
if (ctx->unscaled)
if (ctx->unscaled) // Just perform straight pixel conversion.
{
ctx->direct_pixconv(output, input,
ctx->out_width, ctx->out_height,
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)
{
@ -230,4 +269,3 @@ void scaler_ctx_scale(struct scaler_ctx *ctx,
#endif
}

View File

@ -63,6 +63,8 @@ struct scaler_ctx
const void*, int);
void (*scaler_vert)(const struct scaler_ctx*,
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 (*out_pixconv)(void*, const void*, int, int, int, int);

View File

@ -231,3 +231,33 @@ void scaler_argb8888_horiz(const struct scaler_ctx *ctx, const void *input_, int
}
#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];
}
}

View File

@ -21,5 +21,11 @@
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_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