mirror of
https://github.com/libretro/RetroArch.git
synced 2025-03-03 07:18:56 +00:00
(Softfilter plugs) Identing cleanups
This commit is contained in:
parent
f4332eebbd
commit
9ee74bb5a2
@ -33,8 +33,6 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
// Compile: gcc -o twoxbr.so -shared twoxbr.c -std=c99 -O3 -Wall -pedantic -fPIC
|
||||
|
||||
#include "softfilter.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -233,7 +231,8 @@ static void *twoxbr_generic_create(const struct softfilter_config *config,
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
return NULL;
|
||||
filt->workers = (struct softfilter_thread_data*)calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->workers = (struct softfilter_thread_data*)
|
||||
calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->threads = threads;
|
||||
filt->in_fmt = in_fmt;
|
||||
if (!filt->workers)
|
||||
@ -247,7 +246,8 @@ static void *twoxbr_generic_create(const struct softfilter_config *config,
|
||||
return filt;
|
||||
}
|
||||
|
||||
static void twoxbr_generic_output(void *data, unsigned *out_width, unsigned *out_height,
|
||||
static void twoxbr_generic_output(void *data,
|
||||
unsigned *out_width, unsigned *out_height,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
*out_width = width * TWOXBR_SCALE;
|
||||
@ -261,12 +261,6 @@ static void twoxbr_generic_destroy(void *data)
|
||||
free(filt);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
#define ALPHA_BLEND_128_W(dst, src) dst = ((src & pg_lbmask) >> 1) + ((dst & pg_lbmask) >> 1)
|
||||
|
||||
#define ALPHA_BLEND_32_W(dst, src) \
|
||||
@ -418,7 +412,8 @@ static void twoxbr_generic_destroy(void *data)
|
||||
|
||||
|
||||
|
||||
float df8(uint32_t A, uint32_t B, uint32_t pg_red_mask, uint32_t pg_green_mask, uint32_t pg_blue_mask)
|
||||
float df8(uint32_t A, uint32_t B,
|
||||
uint32_t pg_red_mask, uint32_t pg_green_mask, uint32_t pg_blue_mask)
|
||||
{
|
||||
uint32_t r, g, b;
|
||||
uint32_t y, u, v;
|
||||
@ -440,7 +435,8 @@ float df8(uint32_t A, uint32_t B, uint32_t pg_red_mask, uint32_t pg_green_mask,
|
||||
return 48*y + 7*u + 6*v;
|
||||
}
|
||||
|
||||
int eq8(uint32_t A, uint32_t B, uint32_t pg_red_mask, uint32_t pg_green_mask, uint32_t pg_blue_mask)
|
||||
int eq8(uint32_t A, uint32_t B,
|
||||
uint32_t pg_red_mask, uint32_t pg_green_mask, uint32_t pg_blue_mask)
|
||||
{
|
||||
uint32_t r, g, b;
|
||||
uint32_t y, u, v;
|
||||
@ -600,12 +596,13 @@ static void twoxbr_generic_xrgb8888(void *data, unsigned width, unsigned height,
|
||||
{
|
||||
twoxbr_declare_variables(uint32_t, in, nextline);
|
||||
|
||||
//---------------------------------------
|
||||
// Map of the pixels: A1 B1 C1
|
||||
// A0 PA PB PC C4
|
||||
// D0 PD PE PF F4
|
||||
// G0 PG PH PI I4
|
||||
// G5 H5 I5
|
||||
/*
|
||||
* Map of the pixels: A1 B1 C1
|
||||
* A0 PA PB PC C4
|
||||
* D0 PD PE PF F4
|
||||
* G0 PG PH PI I4
|
||||
* G5 H5 I5
|
||||
*/
|
||||
|
||||
twoxbr_function(FILTRO_RGB8888, filt);
|
||||
}
|
||||
@ -639,12 +636,13 @@ static void twoxbr_generic_rgb565(void *data, unsigned width, unsigned height,
|
||||
{
|
||||
twoxbr_declare_variables(uint16_t, in, nextline);
|
||||
|
||||
//---------------------------------------
|
||||
// Map of the pixels: A1 B1 C1
|
||||
// A0 PA PB PC C4
|
||||
// D0 PD PE PF F4
|
||||
// G0 PG PH PI I4
|
||||
// G5 H5 I5
|
||||
/*
|
||||
* Map of the pixels: A1 B1 C1
|
||||
* A0 PA PB PC C4
|
||||
* D0 PD PE PF F4
|
||||
* G0 PG PH PI I4
|
||||
* G5 H5 I5
|
||||
*/
|
||||
|
||||
twoxbr_function(FILTRO_RGB565, filt);
|
||||
}
|
||||
@ -656,56 +654,68 @@ static void twoxbr_generic_rgb565(void *data, unsigned width, unsigned height,
|
||||
|
||||
static void twoxbr_work_cb_rgb565(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)thread_data;
|
||||
uint16_t *input = (uint16_t*)thr->in_data;
|
||||
uint16_t *output = (uint16_t*)thr->out_data;
|
||||
unsigned width = thr->width;
|
||||
unsigned height = thr->height;
|
||||
|
||||
twoxbr_generic_rgb565(data, width, height,
|
||||
thr->first, thr->last, input, thr->in_pitch / SOFTFILTER_BPP_RGB565, output, thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
thr->first, thr->last, input,
|
||||
thr->in_pitch / SOFTFILTER_BPP_RGB565, output,
|
||||
thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
}
|
||||
|
||||
static void twoxbr_work_cb_xrgb8888(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)thread_data;
|
||||
uint32_t *input = (uint32_t*)thr->in_data;
|
||||
uint32_t *output = (uint32_t*)thr->out_data;
|
||||
unsigned width = thr->width;
|
||||
unsigned height = thr->height;
|
||||
|
||||
twoxbr_generic_xrgb8888(data, width, height,
|
||||
thr->first, thr->last, input, thr->in_pitch / SOFTFILTER_BPP_XRGB8888, output, thr->out_pitch / SOFTFILTER_BPP_XRGB8888);
|
||||
thr->first, thr->last, input,
|
||||
thr->in_pitch / SOFTFILTER_BPP_XRGB8888, output,
|
||||
thr->out_pitch / SOFTFILTER_BPP_XRGB8888);
|
||||
}
|
||||
|
||||
static void twoxbr_generic_packets(void *data,
|
||||
struct softfilter_work_packet *packets,
|
||||
void *output, size_t output_stride,
|
||||
const void *input, unsigned width, unsigned height, size_t input_stride)
|
||||
const void *input, unsigned width,
|
||||
unsigned height, size_t input_stride)
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
unsigned i;
|
||||
for (i = 0; i < filt->threads; i++)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)&filt->workers[i];
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)&filt->workers[i];
|
||||
|
||||
unsigned y_start = (height * i) / filt->threads;
|
||||
unsigned y_end = (height * (i + 1)) / filt->threads;
|
||||
thr->out_data = (uint8_t*)output + y_start * TWOXBR_SCALE * output_stride;
|
||||
thr->out_data = (uint8_t*)output + y_start *
|
||||
TWOXBR_SCALE * output_stride;
|
||||
thr->in_data = (const uint8_t*)input + y_start * input_stride;
|
||||
thr->out_pitch = output_stride;
|
||||
thr->in_pitch = input_stride;
|
||||
thr->width = width;
|
||||
thr->height = y_end - y_start;
|
||||
|
||||
// Workers need to know if they can access pixels outside their given buffer.
|
||||
/* Workers need to know if they can access
|
||||
* pixels outside their given buffer. */
|
||||
thr->first = y_start;
|
||||
thr->last = y_end == height;
|
||||
|
||||
if (filt->in_fmt == SOFTFILTER_FMT_RGB565)
|
||||
packets[i].work = twoxbr_work_cb_rgb565;
|
||||
//else if (filt->in_fmt == SOFTFILTER_FMT_RGB4444)
|
||||
//packets[i].work = twoxbr_work_cb_rgb4444;
|
||||
#if 0
|
||||
else if (filt->in_fmt == SOFTFILTER_FMT_RGB4444)
|
||||
packets[i].work = twoxbr_work_cb_rgb4444;
|
||||
#endif
|
||||
else if (filt->in_fmt == SOFTFILTER_FMT_XRGB8888)
|
||||
packets[i].work = twoxbr_work_cb_xrgb8888;
|
||||
packets[i].thread_data = thr;
|
||||
@ -727,7 +737,8 @@ static const struct softfilter_implementation twoxbr_generic = {
|
||||
"2xbr",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
const struct softfilter_implementation *softfilter_get_implementation(
|
||||
softfilter_simd_mask_t simd)
|
||||
{
|
||||
(void)simd;
|
||||
return &twoxbr_generic;
|
||||
|
@ -14,8 +14,6 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Compile: gcc -o twoxsai.so -shared twoxsai.c -std=c99 -O3 -Wall -pedantic -fPIC
|
||||
|
||||
#include "softfilter.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -76,7 +74,8 @@ static void *twoxsai_generic_create(const struct softfilter_config *config,
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
return NULL;
|
||||
filt->workers = (struct softfilter_thread_data*)calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->workers = (struct softfilter_thread_data*)
|
||||
calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->threads = threads;
|
||||
filt->in_fmt = in_fmt;
|
||||
if (!filt->workers)
|
||||
@ -87,7 +86,8 @@ static void *twoxsai_generic_create(const struct softfilter_config *config,
|
||||
return filt;
|
||||
}
|
||||
|
||||
static void twoxsai_generic_output(void *data, unsigned *out_width, unsigned *out_height,
|
||||
static void twoxsai_generic_output(void *data,
|
||||
unsigned *out_width, unsigned *out_height,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
*out_width = width * TWOXSAI_SCALE;
|
||||
@ -130,8 +130,7 @@ static void twoxsai_generic_destroy(void *data)
|
||||
typename_t colorL = *(in + nextline + 2); \
|
||||
typename_t colorM = *(in + nextline + nextline - 1); \
|
||||
typename_t colorN = *(in + nextline + nextline + 0); \
|
||||
typename_t colorO = *(in + nextline + nextline + 1); \
|
||||
//typename_t colorP = *(in + nextline + nextline + 2);
|
||||
typename_t colorO = *(in + nextline + nextline + 1);
|
||||
|
||||
#ifndef twoxsai_function
|
||||
#define twoxsai_function(result_cb, interpolate_cb, interpolate2_cb) \
|
||||
@ -237,13 +236,15 @@ static void twoxsai_generic_xrgb8888(unsigned width, unsigned height,
|
||||
{
|
||||
twoxsai_declare_variables(uint32_t, in, nextline);
|
||||
|
||||
//---------------------------------------
|
||||
// Map of the pixels: I|E F|J
|
||||
// G|A B|K
|
||||
// H|C D|L
|
||||
// M|N O|P
|
||||
/*
|
||||
* Map of the pixels: I|E F|J
|
||||
* G|A B|K
|
||||
* H|C D|L
|
||||
* M|N O|P
|
||||
*/
|
||||
|
||||
twoxsai_function(twoxsai_result, twoxsai_interpolate_xrgb8888, twoxsai_interpolate2_xrgb8888);
|
||||
twoxsai_function(twoxsai_result, twoxsai_interpolate_xrgb8888,
|
||||
twoxsai_interpolate2_xrgb8888);
|
||||
}
|
||||
|
||||
src += src_stride;
|
||||
@ -267,13 +268,15 @@ static void twoxsai_generic_rgb565(unsigned width, unsigned height,
|
||||
{
|
||||
twoxsai_declare_variables(uint16_t, in, nextline);
|
||||
|
||||
//---------------------------------------
|
||||
// Map of the pixels: I|E F|J
|
||||
// G|A B|K
|
||||
// H|C D|L
|
||||
// M|N O|P
|
||||
/*
|
||||
* Map of the pixels: I|E F|J
|
||||
* G|A B|K
|
||||
* H|C D|L
|
||||
* M|N O|P
|
||||
*/
|
||||
|
||||
twoxsai_function(twoxsai_result, twoxsai_interpolate_rgb565, twoxsai_interpolate2_rgb565);
|
||||
twoxsai_function(twoxsai_result, twoxsai_interpolate_rgb565,
|
||||
twoxsai_interpolate2_rgb565);
|
||||
}
|
||||
|
||||
src += src_stride;
|
||||
@ -283,56 +286,71 @@ static void twoxsai_generic_rgb565(unsigned width, unsigned height,
|
||||
|
||||
static void twoxsai_work_cb_rgb565(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)thread_data;
|
||||
uint16_t *input = (uint16_t*)thr->in_data;
|
||||
uint16_t *output = (uint16_t*)thr->out_data;
|
||||
unsigned width = thr->width;
|
||||
unsigned height = thr->height;
|
||||
|
||||
twoxsai_generic_rgb565(width, height,
|
||||
thr->first, thr->last, input, thr->in_pitch / SOFTFILTER_BPP_RGB565, output, thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
thr->first, thr->last, input,
|
||||
thr->in_pitch / SOFTFILTER_BPP_RGB565,
|
||||
output,
|
||||
thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
}
|
||||
|
||||
static void twoxsai_work_cb_xrgb8888(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)thread_data;
|
||||
uint32_t *input = (uint32_t*)thr->in_data;
|
||||
uint32_t *output = (uint32_t*)thr->out_data;
|
||||
unsigned width = thr->width;
|
||||
unsigned height = thr->height;
|
||||
|
||||
twoxsai_generic_xrgb8888(width, height,
|
||||
thr->first, thr->last, input, thr->in_pitch / SOFTFILTER_BPP_XRGB8888, output, thr->out_pitch / SOFTFILTER_BPP_XRGB8888);
|
||||
thr->first, thr->last, input,
|
||||
thr->in_pitch / SOFTFILTER_BPP_XRGB8888,
|
||||
output,
|
||||
thr->out_pitch / SOFTFILTER_BPP_XRGB8888);
|
||||
}
|
||||
|
||||
static void twoxsai_generic_packets(void *data,
|
||||
struct softfilter_work_packet *packets,
|
||||
void *output, size_t output_stride,
|
||||
const void *input, unsigned width, unsigned height, size_t input_stride)
|
||||
const void *input, unsigned width,
|
||||
unsigned height, size_t input_stride)
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
unsigned i;
|
||||
for (i = 0; i < filt->threads; i++)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)&filt->workers[i];
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)&filt->workers[i];
|
||||
|
||||
unsigned y_start = (height * i) / filt->threads;
|
||||
unsigned y_end = (height * (i + 1)) / filt->threads;
|
||||
thr->out_data = (uint8_t*)output + y_start * TWOXSAI_SCALE * output_stride;
|
||||
thr->out_data = (uint8_t*)output + y_start *
|
||||
TWOXSAI_SCALE * output_stride;
|
||||
thr->in_data = (const uint8_t*)input + y_start * input_stride;
|
||||
thr->out_pitch = output_stride;
|
||||
thr->in_pitch = input_stride;
|
||||
thr->width = width;
|
||||
thr->height = y_end - y_start;
|
||||
|
||||
// Workers need to know if they can access pixels outside their given buffer.
|
||||
/* Workers need to know if they can access pixels
|
||||
* outside their given buffer.
|
||||
*/
|
||||
thr->first = y_start;
|
||||
thr->last = y_end == height;
|
||||
|
||||
if (filt->in_fmt == SOFTFILTER_FMT_RGB565)
|
||||
packets[i].work = twoxsai_work_cb_rgb565;
|
||||
//else if (filt->in_fmt == SOFTFILTER_FMT_RGB4444)
|
||||
//packets[i].work = twoxsai_work_cb_rgb4444;
|
||||
#if 0
|
||||
else if (filt->in_fmt == SOFTFILTER_FMT_RGB4444)
|
||||
packets[i].work = twoxsai_work_cb_rgb4444;
|
||||
#endif
|
||||
else if (filt->in_fmt == SOFTFILTER_FMT_XRGB8888)
|
||||
packets[i].work = twoxsai_work_cb_xrgb8888;
|
||||
packets[i].thread_data = thr;
|
||||
@ -354,7 +372,8 @@ static const struct softfilter_implementation twoxsai_generic = {
|
||||
"2xsai",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
const struct softfilter_implementation *softfilter_get_implementation(
|
||||
softfilter_simd_mask_t simd)
|
||||
{
|
||||
(void)simd;
|
||||
return &twoxsai_generic;
|
||||
|
@ -126,7 +126,8 @@ static void *blargg_ntsc_snes_generic_create(const struct softfilter_config *con
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
return NULL;
|
||||
filt->workers = (struct softfilter_thread_data*)calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->workers = (struct softfilter_thread_data*)
|
||||
calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->threads = threads;
|
||||
filt->in_fmt = in_fmt;
|
||||
if (!filt->workers)
|
||||
@ -141,7 +142,8 @@ static void *blargg_ntsc_snes_generic_create(const struct softfilter_config *con
|
||||
}
|
||||
|
||||
|
||||
static void blargg_ntsc_snes_generic_output(void *data, unsigned *out_width, unsigned *out_height,
|
||||
static void blargg_ntsc_snes_generic_output(void *data,
|
||||
unsigned *out_width, unsigned *out_height,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
*out_width = SNES_NTSC_OUT_WIDTH(width);
|
||||
@ -165,9 +167,11 @@ static void blargg_ntsc_snes_render_rgb565(void *data, int width, int height,
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
if(width <= 256)
|
||||
snes_ntsc_blit(filt->ntsc, input, pitch, filt->burst, width, height, output, outpitch * 2, first, last);
|
||||
snes_ntsc_blit(filt->ntsc, input, pitch, filt->burst,
|
||||
width, height, output, outpitch * 2, first, last);
|
||||
else
|
||||
snes_ntsc_blit_hires(filt->ntsc, input, pitch, filt->burst, width, height, output, outpitch * 2, first, last);
|
||||
snes_ntsc_blit_hires(filt->ntsc, input, pitch, filt->burst,
|
||||
width, height, output, outpitch * 2, first, last);
|
||||
|
||||
filt->burst ^= filt->burst_toggle;
|
||||
}
|
||||
@ -185,14 +189,18 @@ static void blargg_ntsc_snes_rgb565(void *data, unsigned width, unsigned height,
|
||||
|
||||
static void blargg_ntsc_snes_work_cb_rgb565(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)thread_data;
|
||||
uint16_t *input = (uint16_t*)thr->in_data;
|
||||
uint16_t *output = (uint16_t*)thr->out_data;
|
||||
unsigned width = thr->width;
|
||||
unsigned height = thr->height;
|
||||
|
||||
blargg_ntsc_snes_rgb565(data, width, height,
|
||||
thr->first, thr->last, input, thr->in_pitch / SOFTFILTER_BPP_RGB565, output, thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
thr->first, thr->last, input,
|
||||
thr->in_pitch / SOFTFILTER_BPP_RGB565,
|
||||
output,
|
||||
thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
}
|
||||
|
||||
static void blargg_ntsc_snes_generic_packets(void *data,
|
||||
@ -204,7 +212,8 @@ static void blargg_ntsc_snes_generic_packets(void *data,
|
||||
unsigned i;
|
||||
for (i = 0; i < filt->threads; i++)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)&filt->workers[i];
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)&filt->workers[i];
|
||||
|
||||
unsigned y_start = (height * i) / filt->threads;
|
||||
unsigned y_end = (height * (i + 1)) / filt->threads;
|
||||
@ -215,7 +224,8 @@ static void blargg_ntsc_snes_generic_packets(void *data,
|
||||
thr->width = width;
|
||||
thr->height = y_end - y_start;
|
||||
|
||||
// Workers need to know if they can access pixels outside their given buffer.
|
||||
/* Workers need to know if they can
|
||||
* access pixels outside their given buffer. */
|
||||
thr->first = y_start;
|
||||
thr->last = y_end == height;
|
||||
|
||||
@ -240,7 +250,8 @@ static const struct softfilter_implementation blargg_ntsc_snes_generic = {
|
||||
"blargg_ntsc_snes",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
const struct softfilter_implementation *softfilter_get_implementation(
|
||||
softfilter_simd_mask_t simd)
|
||||
{
|
||||
(void)simd;
|
||||
return &blargg_ntsc_snes_generic;
|
||||
|
@ -14,9 +14,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Compile: gcc -o darken.so -shared darken.c -std=c99 -O3 -Wall -pedantic -fPIC
|
||||
|
||||
// Useless filter, just nice as a reference for other filters.
|
||||
/* Useless filter, just nice as a reference for other filters. */
|
||||
|
||||
#include "softfilter.h"
|
||||
#include <stdlib.h>
|
||||
@ -75,7 +73,8 @@ static void *darken_create(const struct softfilter_config *config,
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
return NULL;
|
||||
filt->workers = (struct softfilter_thread_data*)calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->workers = (struct softfilter_thread_data*)
|
||||
calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->threads = threads;
|
||||
filt->in_fmt = in_fmt;
|
||||
if (!filt->workers)
|
||||
@ -102,28 +101,32 @@ static void darken_destroy(void *data)
|
||||
|
||||
static void darken_work_cb_xrgb8888(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)thread_data;
|
||||
const uint32_t *input = (const uint32_t*)thr->in_data;
|
||||
uint32_t *output = (uint32_t*)thr->out_data;
|
||||
unsigned width = thr->width;
|
||||
unsigned height = thr->height;
|
||||
|
||||
unsigned x, y;
|
||||
for (y = 0; y < height; y++, input += thr->in_pitch >> 2, output += thr->out_pitch >> 2)
|
||||
for (y = 0; y < height;
|
||||
y++, input += thr->in_pitch >> 2, output += thr->out_pitch >> 2)
|
||||
for (x = 0; x < width; x++)
|
||||
output[x] = (input[x] >> 2) & (0x3f * 0x01010101);
|
||||
}
|
||||
|
||||
static void darken_work_cb_rgb565(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)thread_data;
|
||||
const uint16_t *input = (const uint16_t*)thr->in_data;
|
||||
uint16_t *output = (uint16_t*)thr->out_data;
|
||||
unsigned width = thr->width;
|
||||
unsigned height = thr->height;
|
||||
|
||||
unsigned x, y;
|
||||
for (y = 0; y < height; y++, input += thr->in_pitch >> 1, output += thr->out_pitch >> 1)
|
||||
for (y = 0; y < height;
|
||||
y++, input += thr->in_pitch >> 1, output += thr->out_pitch >> 1)
|
||||
for (x = 0; x < width; x++)
|
||||
output[x] = (input[x] >> 2) & ((0x7 << 0) | (0xf << 5) | (0x7 << 11));
|
||||
}
|
||||
@ -137,7 +140,8 @@ static void darken_packets(void *data,
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
for (i = 0; i < filt->threads; i++)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)&filt->workers[i];
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)&filt->workers[i];
|
||||
unsigned y_start = (height * i) / filt->threads;
|
||||
unsigned y_end = (height * (i + 1)) / filt->threads;
|
||||
thr->out_data = (uint8_t*)output + y_start * output_stride;
|
||||
@ -170,7 +174,8 @@ static const struct softfilter_implementation darken = {
|
||||
"darken",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
const struct softfilter_implementation *softfilter_get_implementation(
|
||||
softfilter_simd_mask_t simd)
|
||||
{
|
||||
(void)simd;
|
||||
return &darken;
|
||||
|
@ -14,8 +14,6 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Compile: gcc -o epx.so -shared epx.c -std=c99 -O3 -Wall -pedantic -fPIC
|
||||
|
||||
#include "softfilter.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
@ -75,7 +73,8 @@ static void *epx_generic_create(const struct softfilter_config *config,
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
return NULL;
|
||||
filt->workers = (struct softfilter_thread_data*)calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->workers = (struct softfilter_thread_data*)
|
||||
calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->threads = threads;
|
||||
filt->in_fmt = in_fmt;
|
||||
if (!filt->workers)
|
||||
@ -86,7 +85,8 @@ static void *epx_generic_create(const struct softfilter_config *config,
|
||||
return filt;
|
||||
}
|
||||
|
||||
static void epx_generic_output(void *data, unsigned *out_width, unsigned *out_height,
|
||||
static void epx_generic_output(void *data,
|
||||
unsigned *out_width, unsigned *out_height,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
*out_width = width * EPX_SCALE;
|
||||
@ -113,11 +113,12 @@ static void EPX_16 (int width, int height,
|
||||
|
||||
height -= 2;
|
||||
|
||||
// D
|
||||
// A X C
|
||||
// B
|
||||
/* D
|
||||
* A X C
|
||||
* B
|
||||
*/
|
||||
|
||||
// top edge
|
||||
/* top edge */
|
||||
|
||||
sP = (uint16_t *)(src - prevline);
|
||||
lP = (uint16_t *) (src + src_stride);
|
||||
@ -159,10 +160,12 @@ static void EPX_16 (int width, int height,
|
||||
{
|
||||
#ifdef MSB_FIRST
|
||||
*dP1 = (colorX << 16) + colorX;
|
||||
*dP2 = (((colorA == colorB) ? colorA : colorX) << 16) + ((colorB == colorC) ? colorB : colorX);
|
||||
*dP2 = (((colorA == colorB) ? colorA : colorX) << 16) +
|
||||
((colorB == colorC) ? colorB : colorX);
|
||||
#else
|
||||
*dP1 = colorX + (colorX << 16);
|
||||
*dP2 = ((colorA == colorB) ? colorA : colorX) + (((colorB == colorC) ? colorB : colorX) << 16);
|
||||
*dP2 = ((colorA == colorB) ? colorA : colorX) +
|
||||
(((colorB == colorC) ? colorB : colorX) << 16);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@ -172,7 +175,7 @@ static void EPX_16 (int width, int height,
|
||||
dP2++;
|
||||
}
|
||||
|
||||
// right edge
|
||||
/* right edge */
|
||||
|
||||
colorA = colorX;
|
||||
colorX = colorC;
|
||||
@ -194,8 +197,6 @@ static void EPX_16 (int width, int height,
|
||||
src += src_stride;
|
||||
dst += dst_stride << 1;
|
||||
|
||||
//
|
||||
|
||||
for (; height; height--)
|
||||
{
|
||||
sP = (uint16_t *) src;
|
||||
@ -204,7 +205,7 @@ static void EPX_16 (int width, int height,
|
||||
dP1 = (uint32_t *) dst;
|
||||
dP2 = (uint32_t *) (dst + dst_stride);
|
||||
|
||||
// left edge
|
||||
/* left edge */
|
||||
|
||||
colorX = *sP;
|
||||
colorC = *++sP;
|
||||
@ -227,8 +228,6 @@ static void EPX_16 (int width, int height,
|
||||
dP1++;
|
||||
dP2++;
|
||||
|
||||
//
|
||||
|
||||
for (w = width - 2; w; w--)
|
||||
{
|
||||
colorA = colorX;
|
||||
@ -240,11 +239,15 @@ static void EPX_16 (int width, int height,
|
||||
if ((colorA != colorC) && (colorB != colorD))
|
||||
{
|
||||
#ifdef MSB_FIRST
|
||||
*dP1 = (((colorD == colorA) ? colorD : colorX) << 16) + ((colorC == colorD) ? colorC : colorX);
|
||||
*dP2 = (((colorA == colorB) ? colorA : colorX) << 16) + ((colorB == colorC) ? colorB : colorX);
|
||||
*dP1 = (((colorD == colorA) ? colorD : colorX) << 16) +
|
||||
((colorC == colorD) ? colorC : colorX);
|
||||
*dP2 = (((colorA == colorB) ? colorA : colorX) << 16) +
|
||||
((colorB == colorC) ? colorB : colorX);
|
||||
#else
|
||||
*dP1 = ((colorD == colorA) ? colorD : colorX) + (((colorC == colorD) ? colorC : colorX) << 16);
|
||||
*dP2 = ((colorA == colorB) ? colorA : colorX) + (((colorB == colorC) ? colorB : colorX) << 16);
|
||||
*dP1 = ((colorD == colorA) ? colorD : colorX) +
|
||||
(((colorC == colorD) ? colorC : colorX) << 16);
|
||||
*dP2 = ((colorA == colorB) ? colorA : colorX) +
|
||||
(((colorB == colorC) ? colorB : colorX) << 16);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@ -254,7 +257,7 @@ static void EPX_16 (int width, int height,
|
||||
dP2++;
|
||||
}
|
||||
|
||||
// right edge
|
||||
/* right edge */
|
||||
|
||||
colorA = colorX;
|
||||
colorX = colorC;
|
||||
@ -278,14 +281,14 @@ static void EPX_16 (int width, int height,
|
||||
dst += dst_stride << 1;
|
||||
}
|
||||
|
||||
// bottom edge
|
||||
/* bottom edge */
|
||||
|
||||
sP = (uint16_t *) src;
|
||||
uP = (uint16_t *) (src - src_stride);
|
||||
dP1 = (uint32_t *) dst;
|
||||
dP2 = (uint32_t *) (dst + dst_stride);
|
||||
|
||||
// left edge
|
||||
/* left edge */
|
||||
|
||||
colorX = *sP;
|
||||
colorC = *++sP;
|
||||
@ -307,8 +310,6 @@ static void EPX_16 (int width, int height,
|
||||
dP1++;
|
||||
dP2++;
|
||||
|
||||
//
|
||||
|
||||
for (w = width - 2; w; w--)
|
||||
{
|
||||
colorA = colorX;
|
||||
@ -319,10 +320,12 @@ static void EPX_16 (int width, int height,
|
||||
if ((colorA != colorC) && (colorX != colorD))
|
||||
{
|
||||
#ifdef MSB_FIRST
|
||||
*dP1 = (((colorD == colorA) ? colorD : colorX) << 16) + ((colorC == colorD) ? colorC : colorX);
|
||||
*dP1 = (((colorD == colorA) ? colorD : colorX) << 16) +
|
||||
((colorC == colorD) ? colorC : colorX);
|
||||
*dP2 = (colorX << 16) + colorX;
|
||||
#else
|
||||
*dP1 = ((colorD == colorA) ? colorD : colorX) + (((colorC == colorD) ? colorC : colorX) << 16);
|
||||
*dP1 = ((colorD == colorA) ? colorD : colorX) +
|
||||
(((colorC == colorD) ? colorC : colorX) << 16);
|
||||
*dP2 = colorX + (colorX << 16);
|
||||
#endif
|
||||
}
|
||||
@ -333,7 +336,7 @@ static void EPX_16 (int width, int height,
|
||||
dP2++;
|
||||
}
|
||||
|
||||
// right edge
|
||||
/* right edge */
|
||||
|
||||
colorA = colorX;
|
||||
colorX = colorC;
|
||||
@ -366,14 +369,18 @@ static void epx_generic_rgb565(unsigned width, unsigned height,
|
||||
|
||||
static void epx_work_cb_rgb565(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)thread_data;
|
||||
uint16_t *input = (uint16_t*)thr->in_data;
|
||||
uint16_t *output = (uint16_t*)thr->out_data;
|
||||
unsigned width = thr->width;
|
||||
unsigned height = thr->height;
|
||||
|
||||
epx_generic_rgb565(width, height,
|
||||
thr->first, thr->last, input, thr->in_pitch / SOFTFILTER_BPP_RGB565, output, thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
thr->first, thr->last, input,
|
||||
thr->in_pitch / SOFTFILTER_BPP_RGB565,
|
||||
output,
|
||||
thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
}
|
||||
|
||||
|
||||
@ -386,7 +393,8 @@ static void epx_generic_packets(void *data,
|
||||
unsigned i;
|
||||
for (i = 0; i < filt->threads; i++)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)&filt->workers[i];
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)&filt->workers[i];
|
||||
|
||||
unsigned y_start = (height * i) / filt->threads;
|
||||
unsigned y_end = (height * (i + 1)) / filt->threads;
|
||||
@ -397,7 +405,8 @@ static void epx_generic_packets(void *data,
|
||||
thr->width = width;
|
||||
thr->height = y_end - y_start;
|
||||
|
||||
// Workers need to know if they can access pixels outside their given buffer.
|
||||
/* Workers need to know if they can
|
||||
* access pixels outside their given buffer. */
|
||||
thr->first = y_start;
|
||||
thr->last = y_end == height;
|
||||
|
||||
@ -422,7 +431,8 @@ static const struct softfilter_implementation epx_generic = {
|
||||
"epx",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
const struct softfilter_implementation *softfilter_get_implementation(
|
||||
softfilter_simd_mask_t simd)
|
||||
{
|
||||
(void)simd;
|
||||
return &epx_generic;
|
||||
|
@ -14,8 +14,6 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Compile: gcc -o lq2x.so -shared lq2x.c -std=c99 -O3 -Wall -pedantic -fPIC
|
||||
|
||||
#include "softfilter.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
@ -75,7 +73,8 @@ static void *lq2x_generic_create(const struct softfilter_config *config,
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
return NULL;
|
||||
filt->workers = (struct softfilter_thread_data*)calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->workers = (struct softfilter_thread_data*)
|
||||
calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->threads = threads;
|
||||
filt->in_fmt = in_fmt;
|
||||
if (!filt->workers)
|
||||
@ -86,7 +85,8 @@ static void *lq2x_generic_create(const struct softfilter_config *config,
|
||||
return filt;
|
||||
}
|
||||
|
||||
static void lq2x_generic_output(void *data, unsigned *out_width, unsigned *out_height,
|
||||
static void lq2x_generic_output(void *data,
|
||||
unsigned *out_width, unsigned *out_height,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
*out_width = width * LQ2X_SCALE;
|
||||
@ -194,19 +194,24 @@ static void lq2x_generic_xrgb8888(unsigned width, unsigned height,
|
||||
|
||||
static void lq2x_work_cb_rgb565(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)thread_data;
|
||||
uint16_t *input = (uint16_t*)thr->in_data;
|
||||
uint16_t *output = (uint16_t*)thr->out_data;
|
||||
unsigned width = thr->width;
|
||||
unsigned height = thr->height;
|
||||
|
||||
lq2x_generic_rgb565(width, height,
|
||||
thr->first, thr->last, input, thr->in_pitch / SOFTFILTER_BPP_RGB565, output, thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
thr->first, thr->last, input,
|
||||
thr->in_pitch / SOFTFILTER_BPP_RGB565,
|
||||
output,
|
||||
thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
}
|
||||
|
||||
static void lq2x_work_cb_xrgb8888(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)thread_data;
|
||||
uint32_t *input = (uint32_t*)thr->in_data;
|
||||
uint32_t *output = (uint32_t*)thr->out_data;
|
||||
unsigned width = thr->width;
|
||||
@ -215,19 +220,24 @@ static void lq2x_work_cb_xrgb8888(void *data, void *thread_data)
|
||||
(void)data;
|
||||
|
||||
lq2x_generic_xrgb8888(width, height,
|
||||
thr->first, thr->last, input, thr->in_pitch / SOFTFILTER_BPP_XRGB8888, output, thr->out_pitch / SOFTFILTER_BPP_XRGB8888);
|
||||
thr->first, thr->last, input,
|
||||
thr->in_pitch / SOFTFILTER_BPP_XRGB8888,
|
||||
output,
|
||||
thr->out_pitch / SOFTFILTER_BPP_XRGB8888);
|
||||
}
|
||||
|
||||
static void lq2x_generic_packets(void *data,
|
||||
struct softfilter_work_packet *packets,
|
||||
void *output, size_t output_stride,
|
||||
const void *input, unsigned width, unsigned height, size_t input_stride)
|
||||
const void *input, unsigned width,
|
||||
unsigned height, size_t input_stride)
|
||||
{
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
unsigned i;
|
||||
for (i = 0; i < filt->threads; i++)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)&filt->workers[i];
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)&filt->workers[i];
|
||||
|
||||
unsigned y_start = (height * i) / filt->threads;
|
||||
unsigned y_end = (height * (i + 1)) / filt->threads;
|
||||
@ -238,14 +248,17 @@ static void lq2x_generic_packets(void *data,
|
||||
thr->width = width;
|
||||
thr->height = y_end - y_start;
|
||||
|
||||
// Workers need to know if they can access pixels outside their given buffer.
|
||||
/* Workers need to know if they can access pixels
|
||||
* outside their given buffer. */
|
||||
thr->first = y_start;
|
||||
thr->last = y_end == height;
|
||||
|
||||
if (filt->in_fmt == SOFTFILTER_FMT_RGB565)
|
||||
packets[i].work = lq2x_work_cb_rgb565;
|
||||
//else if (filt->in_fmt == SOFTFILTER_FMT_RGB4444)
|
||||
//packets[i].work = lq2x_work_cb_rgb4444;
|
||||
#if 0
|
||||
else if (filt->in_fmt == SOFTFILTER_FMT_RGB4444)
|
||||
packets[i].work = lq2x_work_cb_rgb4444;
|
||||
#endif
|
||||
else if (filt->in_fmt == SOFTFILTER_FMT_XRGB8888)
|
||||
packets[i].work = lq2x_work_cb_xrgb8888;
|
||||
packets[i].thread_data = thr;
|
||||
@ -267,7 +280,8 @@ static const struct softfilter_implementation lq2x_generic = {
|
||||
"lq2x",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
const struct softfilter_implementation *softfilter_get_implementation(
|
||||
softfilter_simd_mask_t simd)
|
||||
{
|
||||
(void)simd;
|
||||
return &lq2x_generic;
|
||||
|
@ -14,8 +14,6 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Compile: gcc -o phosphor2x.so -shared phosphor2x.c -std=c99 -O3 -Wall -pedantic -fPIC
|
||||
|
||||
#include "softfilter.h"
|
||||
#include "boolean.h"
|
||||
#include <stdlib.h>
|
||||
@ -106,96 +104,111 @@ static inline unsigned max_component_rgb565(uint32_t color)
|
||||
return max;
|
||||
}
|
||||
|
||||
static void blit_linear_line_xrgb8888(uint32_t * out, const uint32_t *in, unsigned width)
|
||||
static void blit_linear_line_xrgb8888(uint32_t * out,
|
||||
const uint32_t *in, unsigned width)
|
||||
{
|
||||
unsigned i;
|
||||
// Splat pixels out on the line.
|
||||
|
||||
/* Splat pixels out on the line. */
|
||||
for (i = 0; i < width; i++)
|
||||
out[i << 1] = in[i];
|
||||
|
||||
// Blend in-between pixels.
|
||||
/* Blend in-between pixels. */
|
||||
for (i = 1; i < (width << 1) - 1; i += 2)
|
||||
out[i] = blend_pixels_xrgb8888(out[i - 1], out[i + 1]);
|
||||
|
||||
// Blend edge pixels against black.
|
||||
/* Blend edge pixels against black. */
|
||||
out[0] = blend_pixels_xrgb8888(out[0], 0);
|
||||
out[(width << 1) - 1] = blend_pixels_xrgb8888(out[(width << 1) - 1], 0);
|
||||
out[(width << 1) - 1] =
|
||||
blend_pixels_xrgb8888(out[(width << 1) - 1], 0);
|
||||
}
|
||||
|
||||
static void blit_linear_line_rgb565(uint16_t * out, const uint16_t *in, unsigned width)
|
||||
static void blit_linear_line_rgb565(uint16_t * out,
|
||||
const uint16_t *in, unsigned width)
|
||||
{
|
||||
unsigned i;
|
||||
// Splat pixels out on the line.
|
||||
|
||||
/* Splat pixels out on the line. */
|
||||
for (i = 0; i < width; i++)
|
||||
out[i << 1] = in[i];
|
||||
|
||||
// Blend in-between pixels.
|
||||
/* Blend in-between pixels. */
|
||||
for (i = 1; i < (width << 1) - 1; i += 2)
|
||||
out[i] = blend_pixels_rgb565(out[i - 1], out[i + 1]);
|
||||
out[i] =
|
||||
blend_pixels_rgb565(out[i - 1], out[i + 1]);
|
||||
|
||||
// Blend edge pixels against black.
|
||||
/* Blend edge pixels against black. */
|
||||
out[0] = blend_pixels_rgb565(out[0], 0);
|
||||
out[(width << 1) - 1] = blend_pixels_rgb565(out[(width << 1) - 1], 0);
|
||||
out[(width << 1) - 1] =
|
||||
blend_pixels_rgb565(out[(width << 1) - 1], 0);
|
||||
}
|
||||
|
||||
static void bleed_phosphors_xrgb8888(void *data, uint32_t *scanline, unsigned width)
|
||||
static void bleed_phosphors_xrgb8888(void *data,
|
||||
uint32_t *scanline, unsigned width)
|
||||
{
|
||||
unsigned x;
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
|
||||
// Red phosphor
|
||||
/* Red phosphor */
|
||||
for (x = 0; x < width; x += 2)
|
||||
{
|
||||
unsigned r = red_xrgb8888(scanline[x]);
|
||||
unsigned r_set = clamp8(r * filt->phosphor_bleed * filt->phosphor_bloom_8888[r]);
|
||||
unsigned r_set = clamp8(r * filt->phosphor_bleed *
|
||||
filt->phosphor_bloom_8888[r]);
|
||||
set_red_xrgb8888(scanline[x + 1], r_set);
|
||||
}
|
||||
|
||||
// Green phosphor
|
||||
/* Green phosphor */
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
unsigned g = green_xrgb8888(scanline[x]);
|
||||
unsigned g_set = clamp8((g >> 1) + 0.5 * g * filt->phosphor_bleed * filt->phosphor_bloom_8888[g]);
|
||||
unsigned g_set = clamp8((g >> 1) + 0.5 * g *
|
||||
filt->phosphor_bleed * filt->phosphor_bloom_8888[g]);
|
||||
set_green_xrgb8888(scanline[x], g_set);
|
||||
}
|
||||
|
||||
// Blue phosphor
|
||||
/* Blue phosphor */
|
||||
set_blue_xrgb8888(scanline[0], 0);
|
||||
for (x = 1; x < width; x += 2)
|
||||
{
|
||||
unsigned b = blue_xrgb8888(scanline[x]);
|
||||
unsigned b_set = clamp8(b * filt->phosphor_bleed * filt->phosphor_bloom_8888[b]);
|
||||
unsigned b_set = clamp8(b * filt->phosphor_bleed *
|
||||
filt->phosphor_bloom_8888[b]);
|
||||
set_blue_xrgb8888(scanline[x + 1], b_set);
|
||||
}
|
||||
}
|
||||
|
||||
static void bleed_phosphors_rgb565(void *data, uint16_t *scanline, unsigned width)
|
||||
static void bleed_phosphors_rgb565(void *data,
|
||||
uint16_t *scanline, unsigned width)
|
||||
{
|
||||
unsigned x;
|
||||
struct filter_data *filt = (struct filter_data*)data;
|
||||
|
||||
// Red phosphor
|
||||
/* Red phosphor */
|
||||
for (x = 0; x < width; x += 2)
|
||||
{
|
||||
unsigned r = red_rgb565(scanline[x]);
|
||||
unsigned r_set = clamp6(r * filt->phosphor_bleed * filt->phosphor_bloom_565[r]);
|
||||
unsigned r_set = clamp6(r * filt->phosphor_bleed *
|
||||
filt->phosphor_bloom_565[r]);
|
||||
set_red_rgb565(scanline[x + 1], r_set);
|
||||
}
|
||||
|
||||
// Green phosphor
|
||||
/* Green phosphor */
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
unsigned g = green_rgb565(scanline[x]);
|
||||
unsigned g_set = clamp6((g >> 1) + 0.5 * g * filt->phosphor_bleed * filt->phosphor_bloom_565[g]);
|
||||
unsigned g_set = clamp6((g >> 1) + 0.5 * g *
|
||||
filt->phosphor_bleed * filt->phosphor_bloom_565[g]);
|
||||
set_green_rgb565(scanline[x], g_set);
|
||||
}
|
||||
|
||||
// Blue phosphor
|
||||
/* Blue phosphor */
|
||||
set_blue_rgb565(scanline[0], 0);
|
||||
for (x = 1; x < width; x += 2)
|
||||
{
|
||||
unsigned b = blue_rgb565(scanline[x]);
|
||||
unsigned b_set = clamp6(b * filt->phosphor_bleed * filt->phosphor_bloom_565[b]);
|
||||
unsigned b_set = clamp6(b * filt->phosphor_bleed *
|
||||
filt->phosphor_bloom_565[b]);
|
||||
set_blue_rgb565(scanline[x + 1], b_set);
|
||||
}
|
||||
}
|
||||
@ -233,7 +246,8 @@ static void *phosphor2x_generic_create(const struct softfilter_config *config,
|
||||
|
||||
if (!filt)
|
||||
return NULL;
|
||||
filt->workers = (struct softfilter_thread_data*)calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->workers = (struct softfilter_thread_data*)
|
||||
calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->threads = threads;
|
||||
filt->in_fmt = in_fmt;
|
||||
if (!filt->workers)
|
||||
@ -248,24 +262,36 @@ static void *phosphor2x_generic_create(const struct softfilter_config *config,
|
||||
filt->scanrange_low = 0.5;
|
||||
filt->scanrange_high = 0.65;
|
||||
|
||||
// Init lookup tables:
|
||||
// phosphorBloom = (scaleTimes .* linspace(0, 1, 255) .^ (1/2.2)) + scaleAdd;
|
||||
// Not exactly sure of order of operations here ...
|
||||
#if 0
|
||||
/* Initialize lookup tables: */
|
||||
phosphorBloom = (scaleTimes .*
|
||||
linspace(0, 1, 255) .^ (1/2.2)) + scaleAdd;
|
||||
/* Not exactly sure of order of operations here ... */
|
||||
#endif
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
filt->phosphor_bloom_8888[i] = filt->scale_times * powf((float)i / 255.0f, 1.0f/2.2f) + filt->scale_add;
|
||||
filt->scan_range_8888[i] = filt->scanrange_low + i * (filt->scanrange_high - filt->scanrange_low) / 255.0f;
|
||||
filt->phosphor_bloom_8888[i] =
|
||||
filt->scale_times * powf((float)i / 255.0f, 1.0f/2.2f) +
|
||||
filt->scale_add;
|
||||
filt->scan_range_8888[i] =
|
||||
filt->scanrange_low + i *
|
||||
(filt->scanrange_high - filt->scanrange_low) / 255.0f;
|
||||
}
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
filt->phosphor_bloom_565[i] = filt->scale_times * powf((float)i / 31.0f, 1.0f/2.2f) + filt->scale_add;
|
||||
filt->scan_range_565[i] = filt->scanrange_low + i * (filt->scanrange_high - filt->scanrange_low) / 31.0f;
|
||||
filt->phosphor_bloom_565[i] =
|
||||
filt->scale_times * powf((float)i / 31.0f, 1.0f/2.2f)
|
||||
+ filt->scale_add;
|
||||
filt->scan_range_565[i] =
|
||||
filt->scanrange_low + i *
|
||||
(filt->scanrange_high - filt->scanrange_low) / 31.0f;
|
||||
}
|
||||
|
||||
return filt;
|
||||
}
|
||||
|
||||
static void phosphor2x_generic_output(void *data, unsigned *out_width, unsigned *out_height,
|
||||
static void phosphor2x_generic_output(void *data,
|
||||
unsigned *out_width, unsigned *out_height,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
(void)data;
|
||||
@ -280,7 +306,8 @@ static void phosphor2x_generic_destroy(void *data)
|
||||
free(filt);
|
||||
}
|
||||
|
||||
static void phosphor2x_generic_xrgb8888(void *data, unsigned width, unsigned height,
|
||||
static void phosphor2x_generic_xrgb8888(void *data,
|
||||
unsigned width, unsigned height,
|
||||
int first, int last, uint32_t *src,
|
||||
unsigned src_stride, uint32_t *dst, unsigned dst_stride)
|
||||
{
|
||||
@ -296,28 +323,39 @@ static void phosphor2x_generic_xrgb8888(void *data, unsigned width, unsigned hei
|
||||
{
|
||||
uint32_t *out_line, *scan_out;
|
||||
unsigned x;
|
||||
const uint32_t *in_line = (const uint32_t*)(src + y * (src_stride)); // Input
|
||||
const uint32_t *in_line = (const uint32_t*)(src + y * (src_stride));
|
||||
|
||||
out_line = (uint32_t*)(dst + y * (dst_stride) * 2); // Output in a scanlines fashion.
|
||||
/* output in a scanlines fashion. */
|
||||
out_line = (uint32_t*)(dst + y * (dst_stride) * 2);
|
||||
|
||||
blit_linear_line_xrgb8888(out_line, in_line, width); // Bilinear stretch horizontally.
|
||||
bleed_phosphors_xrgb8888(filt, out_line, width << 1); // Mask 'n bleed phosphors.
|
||||
/* Bilinear stretch horizontally. */
|
||||
blit_linear_line_xrgb8888(out_line, in_line, width);
|
||||
|
||||
// Apply scanlines
|
||||
/* Mask 'n bleed phosphors */
|
||||
bleed_phosphors_xrgb8888(filt, out_line, width << 1);
|
||||
|
||||
/* Apply scanlines */
|
||||
|
||||
scan_out = (uint32_t*)out_line + (dst_stride);
|
||||
|
||||
for (x = 0; x < (width << 1); x++)
|
||||
{
|
||||
unsigned max = max_component_xrgb8888(out_line[x]);
|
||||
set_red_xrgb8888(scan_out[x], (uint32_t)(filt->scan_range_8888[max] * red_xrgb8888(out_line[x])));
|
||||
set_green_xrgb8888(scan_out[x], (uint32_t)(filt->scan_range_8888[max] * green_xrgb8888(out_line[x])));
|
||||
set_blue_xrgb8888(scan_out[x], (uint32_t)(filt->scan_range_8888[max] * blue_xrgb8888(out_line[x])));
|
||||
set_red_xrgb8888(scan_out[x],
|
||||
(uint32_t)(filt->scan_range_8888[max] *
|
||||
red_xrgb8888(out_line[x])));
|
||||
set_green_xrgb8888(scan_out[x],
|
||||
(uint32_t)(filt->scan_range_8888[max] *
|
||||
green_xrgb8888(out_line[x])));
|
||||
set_blue_xrgb8888(scan_out[x],
|
||||
(uint32_t)(filt->scan_range_8888[max] *
|
||||
blue_xrgb8888(out_line[x])));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void phosphor2x_generic_rgb565(void *data, unsigned width, unsigned height,
|
||||
static void phosphor2x_generic_rgb565(void *data,
|
||||
unsigned width, unsigned height,
|
||||
int first, int last, uint16_t *src,
|
||||
unsigned src_stride, uint16_t *dst, unsigned dst_stride)
|
||||
{
|
||||
@ -333,48 +371,65 @@ static void phosphor2x_generic_rgb565(void *data, unsigned width, unsigned heigh
|
||||
{
|
||||
uint16_t *scan_out;
|
||||
unsigned x;
|
||||
uint16_t *out_line = (uint16_t*)(dst + y * (dst_stride) * 2); // Output in a scanlines fashion.
|
||||
const uint16_t *in_line = (const uint16_t*)(src + y * (src_stride)); // Input
|
||||
/* Output in a scanlines fashion. */
|
||||
uint16_t *out_line = (uint16_t*)(dst + y * (dst_stride) * 2);
|
||||
const uint16_t *in_line = (const uint16_t*)(src + y * (src_stride));
|
||||
|
||||
blit_linear_line_rgb565(out_line, in_line, width); // Bilinear stretch horizontally.
|
||||
bleed_phosphors_rgb565(filt, out_line, width << 1); // Mask 'n bleed phosphors.
|
||||
/* Bilinear stretch horizontally. */
|
||||
blit_linear_line_rgb565(out_line, in_line, width);
|
||||
|
||||
// Apply scanlines.
|
||||
/* Mask 'n bleed phosphors. */
|
||||
bleed_phosphors_rgb565(filt, out_line, width << 1);
|
||||
|
||||
/* Apply scanlines. */
|
||||
scan_out = (uint16_t*)(out_line + (dst_stride));
|
||||
|
||||
for (x = 0; x < (width << 1); x++)
|
||||
{
|
||||
unsigned max = max_component_rgb565(out_line[x]);
|
||||
set_red_rgb565(scan_out[x], (uint16_t)(filt->scan_range_565[max] * red_rgb565(out_line[x])));
|
||||
set_green_rgb565(scan_out[x], (uint16_t)(filt->scan_range_565[max] * green_rgb565(out_line[x])));
|
||||
set_blue_rgb565(scan_out[x], (uint16_t)(filt->scan_range_565[max] * blue_rgb565(out_line[x])));
|
||||
set_red_rgb565(scan_out[x],
|
||||
(uint16_t)(filt->scan_range_565[max] *
|
||||
red_rgb565(out_line[x])));
|
||||
set_green_rgb565(scan_out[x],
|
||||
(uint16_t)(filt->scan_range_565[max] *
|
||||
green_rgb565(out_line[x])));
|
||||
set_blue_rgb565(scan_out[x],
|
||||
(uint16_t)(filt->scan_range_565[max] *
|
||||
blue_rgb565(out_line[x])));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void phosphor2x_work_cb_xrgb8888(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)thread_data;
|
||||
uint32_t *input = (uint32_t*)thr->in_data;
|
||||
uint32_t *output = (uint32_t*)thr->out_data;
|
||||
unsigned width = thr->width;
|
||||
unsigned height = thr->height;
|
||||
|
||||
phosphor2x_generic_xrgb8888(data, width, height,
|
||||
thr->first, thr->last, input, thr->in_pitch / SOFTFILTER_BPP_XRGB8888, output, thr->out_pitch / SOFTFILTER_BPP_XRGB8888);
|
||||
thr->first, thr->last, input,
|
||||
thr->in_pitch / SOFTFILTER_BPP_XRGB8888,
|
||||
output,
|
||||
thr->out_pitch / SOFTFILTER_BPP_XRGB8888);
|
||||
}
|
||||
|
||||
static void phosphor2x_work_cb_rgb565(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)thread_data;
|
||||
uint16_t *input = (uint16_t*)thr->in_data;
|
||||
uint16_t *output = (uint16_t*)thr->out_data;
|
||||
unsigned width = thr->width;
|
||||
unsigned height = thr->height;
|
||||
|
||||
phosphor2x_generic_rgb565(data, width, height,
|
||||
thr->first, thr->last, input, thr->in_pitch / SOFTFILTER_BPP_RGB565, output, thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
thr->first, thr->last, input,
|
||||
thr->in_pitch / SOFTFILTER_BPP_RGB565,
|
||||
output,
|
||||
thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
}
|
||||
|
||||
static void phosphor2x_generic_packets(void *data,
|
||||
@ -386,7 +441,8 @@ static void phosphor2x_generic_packets(void *data,
|
||||
unsigned i;
|
||||
for (i = 0; i < filt->threads; i++)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)&filt->workers[i];
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)&filt->workers[i];
|
||||
|
||||
unsigned y_start = (height * i) / filt->threads;
|
||||
unsigned y_end = (height * (i + 1)) / filt->threads;
|
||||
@ -397,14 +453,17 @@ static void phosphor2x_generic_packets(void *data,
|
||||
thr->width = width;
|
||||
thr->height = y_end - y_start;
|
||||
|
||||
// Workers need to know if they can access pixels outside their given buffer.
|
||||
/* Workers need to know if they can access pixels
|
||||
* outside their given buffer. */
|
||||
thr->first = y_start;
|
||||
thr->last = y_end == height;
|
||||
|
||||
if (filt->in_fmt == SOFTFILTER_FMT_RGB565)
|
||||
packets[i].work = phosphor2x_work_cb_rgb565;
|
||||
//else if (filt->in_fmt == SOFTFILTER_FMT_RGB4444)
|
||||
//packets[i].work = phosphor2x_work_cb_rgb4444;
|
||||
#if 0
|
||||
else if (filt->in_fmt == SOFTFILTER_FMT_RGB4444)
|
||||
packets[i].work = phosphor2x_work_cb_rgb4444;
|
||||
#endif
|
||||
if (filt->in_fmt == SOFTFILTER_FMT_XRGB8888)
|
||||
packets[i].work = phosphor2x_work_cb_xrgb8888;
|
||||
packets[i].thread_data = thr;
|
||||
@ -426,7 +485,8 @@ static const struct softfilter_implementation phosphor2x_generic = {
|
||||
"phosphor2x",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
const struct softfilter_implementation *softfilter_get_implementation(
|
||||
softfilter_simd_mask_t simd)
|
||||
{
|
||||
(void)simd;
|
||||
return &phosphor2x_generic;
|
||||
|
@ -91,7 +91,8 @@ static void scale2x_generic_rgb565(unsigned width, unsigned height,
|
||||
uint16_t *out0, *out1;
|
||||
out0 = (uint16_t*)dst;
|
||||
out1 = (uint16_t*)(dst + dst_stride);
|
||||
SCALE2X_GENERIC(uint16_t, width, height, first, last, src, src_stride, dst, dst_stride, out0, out1);
|
||||
SCALE2X_GENERIC(uint16_t, width, height, first, last,
|
||||
src, src_stride, dst, dst_stride, out0, out1);
|
||||
}
|
||||
|
||||
static void scale2x_generic_xrgb8888(unsigned width, unsigned height,
|
||||
@ -103,7 +104,8 @@ static void scale2x_generic_xrgb8888(unsigned width, unsigned height,
|
||||
uint32_t *out0, *out1;
|
||||
out0 = (uint32_t*)dst;
|
||||
out1 = (uint32_t*)(dst + dst_stride);
|
||||
SCALE2X_GENERIC(uint32_t, width, height, first, last, src, src_stride, dst, dst_stride, out0, out1);
|
||||
SCALE2X_GENERIC(uint32_t, width, height, first, last,
|
||||
src, src_stride, dst, dst_stride, out0, out1);
|
||||
}
|
||||
|
||||
static unsigned scale2x_generic_input_fmts(void)
|
||||
@ -134,7 +136,8 @@ static void *scale2x_generic_create(const struct softfilter_config *config,
|
||||
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
|
||||
if (!filt)
|
||||
return NULL;
|
||||
filt->workers = (struct softfilter_thread_data*)calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->workers = (struct softfilter_thread_data*)
|
||||
calloc(threads, sizeof(struct softfilter_thread_data));
|
||||
filt->threads = threads;
|
||||
filt->in_fmt = in_fmt;
|
||||
if (!filt->workers)
|
||||
@ -145,7 +148,8 @@ static void *scale2x_generic_create(const struct softfilter_config *config,
|
||||
return filt;
|
||||
}
|
||||
|
||||
static void scale2x_generic_output(void *data, unsigned *out_width, unsigned *out_height,
|
||||
static void scale2x_generic_output(void *data,
|
||||
unsigned *out_width, unsigned *out_height,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
*out_width = width * SCALE2X_SCALE;
|
||||
@ -161,26 +165,34 @@ static void scale2x_generic_destroy(void *data)
|
||||
|
||||
static void scale2x_work_cb_xrgb8888(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)thread_data;
|
||||
const uint32_t *input = (const uint32_t*)thr->in_data;
|
||||
uint32_t *output = (uint32_t*)thr->out_data;
|
||||
unsigned width = thr->width;
|
||||
unsigned height = thr->height;
|
||||
|
||||
scale2x_generic_xrgb8888(width, height,
|
||||
thr->first, thr->last, input, thr->in_pitch / SOFTFILTER_BPP_XRGB8888, output, thr->out_pitch / SOFTFILTER_BPP_XRGB8888);
|
||||
thr->first, thr->last, input,
|
||||
thr->in_pitch / SOFTFILTER_BPP_XRGB8888,
|
||||
output,
|
||||
thr->out_pitch / SOFTFILTER_BPP_XRGB8888);
|
||||
}
|
||||
|
||||
static void scale2x_work_cb_rgb565(void *data, void *thread_data)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)thread_data;
|
||||
const uint16_t *input = (const uint16_t*)thr->in_data;
|
||||
uint16_t *output = (uint16_t*)thr->out_data;
|
||||
unsigned width = thr->width;
|
||||
unsigned height = thr->height;
|
||||
|
||||
scale2x_generic_rgb565(width, height,
|
||||
thr->first, thr->last, input, thr->in_pitch / SOFTFILTER_BPP_RGB565, output, thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
thr->first, thr->last, input,
|
||||
thr->in_pitch / SOFTFILTER_BPP_RGB565,
|
||||
output,
|
||||
thr->out_pitch / SOFTFILTER_BPP_RGB565);
|
||||
}
|
||||
|
||||
static void scale2x_generic_packets(void *data,
|
||||
@ -192,18 +204,21 @@ static void scale2x_generic_packets(void *data,
|
||||
unsigned i;
|
||||
for (i = 0; i < filt->threads; i++)
|
||||
{
|
||||
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)&filt->workers[i];
|
||||
struct softfilter_thread_data *thr =
|
||||
(struct softfilter_thread_data*)&filt->workers[i];
|
||||
|
||||
unsigned y_start = (height * i) / filt->threads;
|
||||
unsigned y_end = (height * (i + 1)) / filt->threads;
|
||||
thr->out_data = (uint8_t*)output + y_start * SCALE2X_SCALE * output_stride;
|
||||
thr->out_data = (uint8_t*)output + y_start *
|
||||
SCALE2X_SCALE * output_stride;
|
||||
thr->in_data = (const uint8_t*)input + y_start * input_stride;
|
||||
thr->out_pitch = output_stride;
|
||||
thr->in_pitch = input_stride;
|
||||
thr->width = width;
|
||||
thr->height = y_end - y_start;
|
||||
|
||||
// Workers need to know if they can access pixels outside their given buffer.
|
||||
/* Workers need to know if they can access pixels
|
||||
* outside their given buffer. */
|
||||
thr->first = y_start;
|
||||
thr->last = y_end == height;
|
||||
|
||||
@ -230,7 +245,8 @@ static const struct softfilter_implementation scale2x_generic = {
|
||||
"scale2x",
|
||||
};
|
||||
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd)
|
||||
const struct softfilter_implementation *softfilter_get_implementation(
|
||||
softfilter_simd_mask_t simd)
|
||||
{
|
||||
(void)simd;
|
||||
return &scale2x_generic;
|
||||
|
@ -39,16 +39,22 @@ extern "C" {
|
||||
#define SOFTFILTER_SIMD_VFPU (1 << 13)
|
||||
#define SOFTFILTER_SIMD_PS (1 << 14)
|
||||
|
||||
// A bit-mask of all supported SIMD instruction sets.
|
||||
// Allows an implementation to pick different softfilter_implementation structs.
|
||||
/* A bit-mask of all supported SIMD instruction sets.
|
||||
* Allows an implementation to pick different
|
||||
* softfilter_implementation structs. */
|
||||
typedef unsigned softfilter_simd_mask_t;
|
||||
|
||||
// Returns true if config key was found. Otherwise, returns false, and sets value to default value.
|
||||
typedef int (*softfilter_config_get_float_t)(void *userdata, const char *key, float *value, float default_value);
|
||||
typedef int (*softfilter_config_get_int_t)(void *userdata, const char *key, int *value, int default_value);
|
||||
/* Returns true if config key was found. Otherwise, returns false,
|
||||
* and sets value to default value. */
|
||||
typedef int (*softfilter_config_get_float_t)(void *userdata,
|
||||
const char *key, float *value, float default_value);
|
||||
|
||||
// Allocates an array with values. free() with softfilter_config_free_t.
|
||||
typedef int (*softfilter_config_get_float_array_t)(void *userdata, const char *key,
|
||||
typedef int (*softfilter_config_get_int_t)(void *userdata,
|
||||
const char *key, int *value, int default_value);
|
||||
|
||||
/* Allocates an array with values. free() with softfilter_config_free_t. */
|
||||
typedef int (*softfilter_config_get_float_array_t)(void *userdata,
|
||||
const char *key,
|
||||
float **values, unsigned *out_num_values,
|
||||
const float *default_values, unsigned num_default_values);
|
||||
|
||||
@ -56,9 +62,11 @@ typedef int (*softfilter_config_get_int_array_t)(void *userdata, const char *key
|
||||
int **values, unsigned *out_num_values,
|
||||
const int *default_values, unsigned num_default_values);
|
||||
|
||||
typedef int (*softfilter_config_get_string_t)(void *userdata, const char *key, char **output, const char *default_output);
|
||||
typedef int (*softfilter_config_get_string_t)(void *userdata,
|
||||
const char *key, char **output, const char *default_output);
|
||||
|
||||
// Calls free() in host runtime. Sometimes needed on Windows. free() on NULL is fine.
|
||||
/* Calls free() in host runtime.
|
||||
* Sometimes needed on Windows. free() on NULL is fine. */
|
||||
typedef void (*softfilter_config_free_t)(void *ptr);
|
||||
|
||||
struct softfilter_config
|
||||
@ -70,36 +78,44 @@ struct softfilter_config
|
||||
softfilter_config_get_int_array_t get_int_array;
|
||||
|
||||
softfilter_config_get_string_t get_string;
|
||||
softfilter_config_free_t free; // Avoid problems where softfilter plug and host are linked against different C runtimes.
|
||||
/* Avoid problems where softfilter plug and
|
||||
* host are linked against different C runtimes. */
|
||||
softfilter_config_free_t free;
|
||||
};
|
||||
|
||||
// Dynamic library entrypoint.
|
||||
typedef const struct softfilter_implementation *(*softfilter_get_implementation_t)(softfilter_simd_mask_t);
|
||||
// The same SIMD mask argument is forwarded to create() callback as well to avoid having to keep lots of state around.
|
||||
const struct softfilter_implementation *softfilter_get_implementation(softfilter_simd_mask_t simd);
|
||||
/* Dynamic library entrypoint. */
|
||||
typedef const struct softfilter_implementation
|
||||
*(*softfilter_get_implementation_t)(softfilter_simd_mask_t);
|
||||
|
||||
/* The same SIMD mask argument is forwarded to create() callback
|
||||
* as well to avoid having to keep lots of state around. */
|
||||
const struct softfilter_implementation *softfilter_get_implementation(
|
||||
softfilter_simd_mask_t simd);
|
||||
|
||||
#define SOFTFILTER_API_VERSION 2
|
||||
|
||||
// Required base color formats
|
||||
/* Required base color formats */
|
||||
|
||||
#define SOFTFILTER_FMT_NONE 0
|
||||
#define SOFTFILTER_FMT_RGB565 (1 << 0)
|
||||
#define SOFTFILTER_FMT_XRGB8888 (1 << 1)
|
||||
|
||||
// Optional color formats
|
||||
/* Optional color formats */
|
||||
#define SOFTFILTER_FMT_RGB4444 (1 << 2)
|
||||
|
||||
#define SOFTFILTER_BPP_RGB565 2
|
||||
#define SOFTFILTER_BPP_XRGB8888 4
|
||||
|
||||
// Softfilter implementation.
|
||||
// Returns a bitmask of supported input formats.
|
||||
/* Softfilter implementation.
|
||||
* Returns a bitmask of supported input formats. */
|
||||
typedef unsigned (*softfilter_query_input_formats_t)(void);
|
||||
|
||||
// Returns a bitmask of supported output formats for a given input format.
|
||||
/* Returns a bitmask of supported output formats
|
||||
* for a given input format. */
|
||||
typedef unsigned (*softfilter_query_output_formats_t)(unsigned input_format);
|
||||
|
||||
// In softfilter_process_t, the softfilter implementation submits work units to a worker thread pool.
|
||||
/* In softfilter_process_t, the softfilter implementation
|
||||
* submits work units to a worker thread pool. */
|
||||
typedef void (*softfilter_work_t)(void *data, void *thread_data);
|
||||
struct softfilter_work_packet
|
||||
{
|
||||
@ -107,31 +123,41 @@ struct softfilter_work_packet
|
||||
void *thread_data;
|
||||
};
|
||||
|
||||
// Create a filter with given input and output formats as well as maximum possible input size.
|
||||
// Input sizes can very per call to softfilter_process_t, but they will never be larger than the maximum.
|
||||
typedef void *(*softfilter_create_t)(const struct softfilter_config *config, unsigned in_fmt, unsigned out_fmt,
|
||||
/* Create a filter with given input and output formats as well as
|
||||
* maximum possible input size.
|
||||
*
|
||||
* Input sizes can very per call to softfilter_process_t, but they
|
||||
* will never be larger than the maximum. */
|
||||
typedef void *(*softfilter_create_t)(const struct softfilter_config *config,
|
||||
unsigned in_fmt, unsigned out_fmt,
|
||||
unsigned max_width, unsigned max_height,
|
||||
unsigned threads, softfilter_simd_mask_t simd, void *userdata);
|
||||
|
||||
typedef void (*softfilter_destroy_t)(void *data);
|
||||
|
||||
// Given an input size, query the output size of the filter.
|
||||
// If width and height == max_width/max_height, no other combination of width/height must return a larger size in any dimension.
|
||||
/* Given an input size, query the output size of the filter.
|
||||
* If width and height == max_width/max_height, no other combination
|
||||
* of width/height must return a larger size in any dimension. */
|
||||
typedef void (*softfilter_query_output_size_t)(void *data,
|
||||
unsigned *out_width, unsigned *out_height,
|
||||
unsigned width, unsigned height);
|
||||
|
||||
// First step of processing a frame. The filter submits work by filling in the packets array.
|
||||
// The number of elements in the array is as returned by query_num_threads.
|
||||
// The processing itself happens in worker threads after this returns.
|
||||
/* First step of processing a frame. The filter submits work by
|
||||
* filling in the packets array.
|
||||
*
|
||||
* The number of elements in the array is as returned by query_num_threads.
|
||||
* The processing itself happens in worker threads after this returns.
|
||||
*/
|
||||
typedef void (*softfilter_get_work_packets_t)(void *data,
|
||||
struct softfilter_work_packet *packets,
|
||||
void *output, size_t output_stride,
|
||||
const void *input, unsigned width, unsigned height, size_t input_stride);
|
||||
|
||||
// Returns the number of worker threads the filter will use.
|
||||
// This can differ from the value passed to create() instead the filter cannot be parallelized, etc. The number of threads must be less-or-equal compared to the value passed to create().
|
||||
/* Returns the number of worker threads the filter will use.
|
||||
* This can differ from the value passed to create() instead the filter
|
||||
* cannot be parallelized, etc. The number of threads must be less-or-equal
|
||||
* compared to the value passed to create(). */
|
||||
typedef unsigned (*softfilter_query_num_threads_t)(void *data);
|
||||
/////
|
||||
|
||||
struct softfilter_implementation
|
||||
{
|
||||
@ -145,9 +171,13 @@ struct softfilter_implementation
|
||||
softfilter_query_output_size_t query_output_size;
|
||||
softfilter_get_work_packets_t get_work_packets;
|
||||
|
||||
unsigned api_version; // Must be SOFTFILTER_API_VERSION
|
||||
const char *ident; // Human readable identifier of implementation.
|
||||
const char *short_ident; // Computer-friendly short version of ident. Lower case, no spaces and special characters, etc.
|
||||
/* Must be SOFTFILTER_API_VERSION. */
|
||||
unsigned api_version;
|
||||
/* Human readable identifier of implementation. */
|
||||
const char *ident;
|
||||
/* Computer-friendly short version of ident.
|
||||
* Lower case, no spaces and special characters, etc. */
|
||||
const char *short_ident;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
Loading…
x
Reference in New Issue
Block a user