1+ #include "softfilter.h"
2+ #include <stdlib.h>
3+ #include <string.h>
4+
5+ #ifdef RARCH_INTERNAL
6+ #define softfilter_get_implementation crop_borders_get_implementation
7+ #define softfilter_thread_data crop_borders_softfilter_thread_data
8+ #define filter_data crop_borders_filter_data
9+ #endif
10+
11+ struct softfilter_thread_data
12+ {
13+ void * out_data ;
14+ const void * in_data ;
15+ size_t out_pitch ;
16+ size_t in_pitch ;
17+ unsigned width ;
18+ unsigned height ;
19+ };
20+
21+ struct filter_data
22+ {
23+ struct softfilter_thread_data * workers ;
24+ unsigned in_fmt ;
25+ float crop_x ;
26+ float crop_y ;
27+ };
28+
29+ static unsigned crop_borders_generic_input_fmts (void )
30+ {
31+ return SOFTFILTER_FMT_RGB565 | SOFTFILTER_FMT_XRGB8888 ;
32+ }
33+
34+ static unsigned crop_borders_generic_output_fmts (unsigned input_fmts )
35+ {
36+ return input_fmts ;
37+ }
38+
39+ static unsigned crop_borders_generic_threads (void * data )
40+ {
41+ return 1 ;
42+ }
43+
44+ /* Εδώ είναι η αρχικοποίηση όπως την κάνει το Blargg */
45+ static void crop_borders_initialize (struct filter_data * filt ,
46+ const struct softfilter_config * config ,
47+ void * userdata )
48+ {
49+ /* Το RetroArch θα ψάξει στο .filt για: crop_borders_crop_x */
50+ config -> get_float (userdata , "crop_x" , & filt -> crop_x , 0.0f );
51+ config -> get_float (userdata , "crop_y" , & filt -> crop_y , 0.0f );
52+ }
53+
54+ static void * crop_borders_generic_create (const struct softfilter_config * config ,
55+ unsigned in_fmt , unsigned out_fmt ,
56+ unsigned max_width , unsigned max_height ,
57+ unsigned threads , softfilter_simd_mask_t simd , void * userdata )
58+ {
59+ struct filter_data * filt = (struct filter_data * )calloc (1 , sizeof (* filt ));
60+ if (!filt ) return NULL ;
61+
62+ if (!(filt -> workers = (struct softfilter_thread_data * )calloc (1 , sizeof (struct softfilter_thread_data ))))
63+ {
64+ free (filt );
65+ return NULL ;
66+ }
67+
68+ filt -> in_fmt = in_fmt ;
69+
70+ /* Καλούμε την initialize όπως το Blargg */
71+ crop_borders_initialize (filt , config , userdata );
72+
73+ return filt ;
74+ }
75+
76+ static void crop_borders_generic_output (void * data ,
77+ unsigned * out_width , unsigned * out_height ,
78+ unsigned width , unsigned height )
79+ {
80+ * out_width = width ;
81+ * out_height = height ;
82+ }
83+
84+ static void crop_borders_generic_destroy (void * data )
85+ {
86+ struct filter_data * filt = (struct filter_data * )data ;
87+ if (!filt ) return ;
88+ free (filt -> workers );
89+ free (filt );
90+ }
91+
92+ /* Rendering Logic με Float Coordinates */
93+ static void crop_borders_work_cb_xrgb8888 (void * data , void * thread_data )
94+ {
95+ struct filter_data * filt = (struct filter_data * )data ;
96+ struct softfilter_thread_data * thr = (struct softfilter_thread_data * )thread_data ;
97+ const uint32_t * input = (const uint32_t * )thr -> in_data ;
98+ uint32_t * output = (uint32_t * )thr -> out_data ;
99+ unsigned in_stride = (unsigned )(thr -> in_pitch >> 2 );
100+ unsigned out_stride = (unsigned )(thr -> out_pitch >> 2 );
101+
102+ float visible_w = (float )thr -> width - (filt -> crop_x * 2.0f );
103+ float visible_h = (float )thr -> height - (filt -> crop_y * 2.0f );
104+
105+ if (visible_w <= 0.0f || visible_h <= 0.0f ) return ;
106+
107+ float step_x = visible_w / (float )thr -> width ;
108+ float step_y = visible_h / (float )thr -> height ;
109+
110+ for (unsigned y = 0 ; y < thr -> height ; y ++ )
111+ {
112+ unsigned i_y = (unsigned )(filt -> crop_y + (y * step_y ));
113+ for (unsigned x = 0 ; x < thr -> width ; x ++ )
114+ {
115+ unsigned i_x = (unsigned )(filt -> crop_x + (x * step_x ));
116+ output [y * out_stride + x ] = input [i_y * in_stride + i_x ];
117+ }
118+ }
119+ }
120+
121+ static void crop_borders_work_cb_rgb565 (void * data , void * thread_data )
122+ {
123+ struct filter_data * filt = (struct filter_data * )data ;
124+ struct softfilter_thread_data * thr = (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 in_stride = (unsigned )(thr -> in_pitch >> 1 );
128+ unsigned out_stride = (unsigned )(thr -> out_pitch >> 1 );
129+
130+ float visible_w = (float )thr -> width - (filt -> crop_x * 2.0f );
131+ float visible_h = (float )thr -> height - (filt -> crop_y * 2.0f );
132+
133+ if (visible_w <= 0.0f || visible_h <= 0.0f ) return ;
134+
135+ float step_x = visible_w / (float )thr -> width ;
136+ float step_y = visible_h / (float )thr -> height ;
137+
138+ for (unsigned y = 0 ; y < thr -> height ; y ++ )
139+ {
140+ unsigned i_y = (unsigned )(filt -> crop_y + (y * step_y ));
141+ for (unsigned x = 0 ; x < thr -> width ; x ++ )
142+ {
143+ unsigned i_x = (unsigned )(filt -> crop_x + (x * step_x ));
144+ output [y * out_stride + x ] = input [i_y * in_stride + i_x ];
145+ }
146+ }
147+ }
148+
149+ static void crop_borders_generic_packets (void * data ,
150+ struct softfilter_work_packet * packets ,
151+ void * output , size_t output_stride ,
152+ const void * input , unsigned width , unsigned height , size_t input_stride )
153+ {
154+ struct filter_data * filt = (struct filter_data * )data ;
155+ struct softfilter_thread_data * thr = & filt -> workers [0 ];
156+
157+ thr -> out_data = output ;
158+ thr -> in_data = input ;
159+ thr -> out_pitch = output_stride ;
160+ thr -> in_pitch = input_stride ;
161+ thr -> width = width ;
162+ thr -> height = height ;
163+
164+ if (filt -> in_fmt == SOFTFILTER_FMT_RGB565 )
165+ packets [0 ].work = crop_borders_work_cb_rgb565 ;
166+ else
167+ packets [0 ].work = crop_borders_work_cb_xrgb8888 ;
168+
169+ packets [0 ].thread_data = thr ;
170+ }
171+
172+ static const struct softfilter_implementation crop_borders_generic = {
173+ crop_borders_generic_input_fmts ,
174+ crop_borders_generic_output_fmts ,
175+ crop_borders_generic_create ,
176+ crop_borders_generic_destroy ,
177+ crop_borders_generic_threads ,
178+ crop_borders_generic_output ,
179+ crop_borders_generic_packets ,
180+ SOFTFILTER_API_VERSION ,
181+ "Crop Borders" ,
182+ "crop_borders" ,
183+ };
184+
185+ const struct softfilter_implementation * softfilter_get_implementation (softfilter_simd_mask_t simd )
186+ {
187+ (void )simd ;
188+ return & crop_borders_generic ;
189+ }
190+
191+ #ifdef RARCH_INTERNAL
192+ #undef softfilter_get_implementation
193+ #undef softfilter_thread_data
194+ #undef filter_data
195+ #endif
0 commit comments