1 /*  RetroArch - A frontend for libretro.
2  *  Copyright (C) 2010-2014 - Hans-Kristian Arntzen
3  *  Copyright (C) 2011-2017 - Daniel De Matteis
4  *
5  *  RetroArch is free software: you can redistribute it and/or modify it under the terms
6  *  of the GNU General Public License as published by the Free Software Found-
7  *  ation, either version 3 of the License, or (at your option) any later version.
8  *
9  *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10  *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11  *  PURPOSE.  See the GNU General Public License for more details.
12  *
13  *  You should have received a copy of the GNU General Public License along with RetroArch.
14  *  If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 /* Useless filter, just nice as a reference for other filters. */
18 
19 #include "softfilter.h"
20 #include <stdlib.h>
21 
22 #ifdef RARCH_INTERNAL
23 #define softfilter_get_implementation darken_get_implementation
24 #define softfilter_thread_data darken_softfilter_thread_data
25 #define filter_data darken_filter_data
26 #endif
27 
28 struct softfilter_thread_data
29 {
30    void *out_data;
31    const void *in_data;
32    size_t out_pitch;
33    size_t in_pitch;
34    unsigned colfmt;
35    unsigned width;
36    unsigned height;
37    int first;
38    int last;
39 };
40 
41 struct filter_data
42 {
43    unsigned threads;
44    struct softfilter_thread_data *workers;
45    unsigned in_fmt;
46 };
47 
darken_input_fmts(void)48 static unsigned darken_input_fmts(void)
49 {
50    return SOFTFILTER_FMT_XRGB8888 | SOFTFILTER_FMT_RGB565;
51 }
52 
darken_output_fmts(unsigned input_fmts)53 static unsigned darken_output_fmts(unsigned input_fmts)
54 {
55    return input_fmts;
56 }
57 
darken_threads(void * data)58 static unsigned darken_threads(void *data)
59 {
60    struct filter_data *filt = (struct filter_data*)data;
61    return filt->threads;
62 }
63 
darken_create(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)64 static void *darken_create(const struct softfilter_config *config,
65       unsigned in_fmt, unsigned out_fmt,
66       unsigned max_width, unsigned max_height,
67       unsigned threads, softfilter_simd_mask_t simd, void *userdata)
68 {
69    struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
70    (void)simd;
71    (void)config;
72    (void)userdata;
73    if (!filt)
74       return NULL;
75    filt->workers = (struct softfilter_thread_data*)
76       calloc(threads, sizeof(struct softfilter_thread_data));
77    filt->threads = threads;
78    filt->in_fmt  = in_fmt;
79    if (!filt->workers)
80    {
81       free(filt);
82       return NULL;
83    }
84    return filt;
85 }
86 
darken_output(void * data,unsigned * out_width,unsigned * out_height,unsigned width,unsigned height)87 static void darken_output(void *data, unsigned *out_width, unsigned *out_height,
88       unsigned width, unsigned height)
89 {
90    *out_width = width;
91    *out_height = height;
92 }
93 
darken_destroy(void * data)94 static void darken_destroy(void *data)
95 {
96    struct filter_data *filt = (struct filter_data*)data;
97 
98    if (!filt)
99       return;
100 
101    free(filt->workers);
102    free(filt);
103 }
104 
darken_work_cb_xrgb8888(void * data,void * thread_data)105 static void darken_work_cb_xrgb8888(void *data, void *thread_data)
106 {
107    struct softfilter_thread_data *thr =
108       (struct softfilter_thread_data*)thread_data;
109    const uint32_t *input = (const uint32_t*)thr->in_data;
110    uint32_t *output = (uint32_t*)thr->out_data;
111    unsigned width = thr->width;
112    unsigned height = thr->height;
113 
114    unsigned x, y;
115    for (y = 0; y < height;
116          y++, input += thr->in_pitch >> 2, output += thr->out_pitch >> 2)
117       for (x = 0; x < width; x++)
118          output[x] = (input[x] >> 2) & (0x3f * 0x01010101);
119 }
120 
darken_work_cb_rgb565(void * data,void * thread_data)121 static void darken_work_cb_rgb565(void *data, void *thread_data)
122 {
123    struct softfilter_thread_data *thr =
124       (struct softfilter_thread_data*)thread_data;
125    const uint16_t *input = (const uint16_t*)thr->in_data;
126    uint16_t *output = (uint16_t*)thr->out_data;
127    unsigned width = thr->width;
128    unsigned height = thr->height;
129 
130    unsigned x, y;
131    for (y = 0; y < height;
132          y++, input += thr->in_pitch >> 1, output += thr->out_pitch >> 1)
133       for (x = 0; x < width; x++)
134          output[x] = (input[x] >> 2) & ((0x7 << 0) | (0xf << 5) | (0x7 << 11));
135 }
136 
darken_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)137 static void darken_packets(void *data,
138       struct softfilter_work_packet *packets,
139       void *output, size_t output_stride,
140       const void *input, unsigned width, unsigned height, size_t input_stride)
141 {
142    unsigned i;
143    struct filter_data *filt = (struct filter_data*)data;
144    for (i = 0; i < filt->threads; i++)
145    {
146       struct softfilter_thread_data *thr =
147          (struct softfilter_thread_data*)&filt->workers[i];
148       unsigned y_start = (height * i) / filt->threads;
149       unsigned y_end = (height * (i + 1)) / filt->threads;
150       thr->out_data = (uint8_t*)output + y_start * output_stride;
151       thr->in_data = (const uint8_t*)input + y_start * input_stride;
152       thr->out_pitch = output_stride;
153       thr->in_pitch = input_stride;
154       thr->width = width;
155       thr->height = y_end - y_start;
156 
157       if (filt->in_fmt == SOFTFILTER_FMT_XRGB8888)
158          packets[i].work = darken_work_cb_xrgb8888;
159       else if (filt->in_fmt == SOFTFILTER_FMT_RGB565)
160          packets[i].work = darken_work_cb_rgb565;
161       packets[i].thread_data = thr;
162    }
163 }
164 
165 static const struct softfilter_implementation darken = {
166    darken_input_fmts,
167    darken_output_fmts,
168 
169    darken_create,
170    darken_destroy,
171 
172    darken_threads,
173    darken_output,
174    darken_packets,
175    SOFTFILTER_API_VERSION,
176    "Darken",
177    "darken",
178 };
179 
softfilter_get_implementation(softfilter_simd_mask_t simd)180 const struct softfilter_implementation *softfilter_get_implementation(
181       softfilter_simd_mask_t simd)
182 {
183    (void)simd;
184    return &darken;
185 }
186 
187 #ifdef RARCH_INTERNAL
188 #undef softfilter_get_implementation
189 #undef softfilter_thread_data
190 #undef filter_data
191 #endif
192