1 /* Copyright  (C) 2010-2019 The RetroArch team
2  *
3  * ---------------------------------------------------------------------------------------
4  * The following license statement only applies to this file (gfx_thumbnail.c).
5  * ---------------------------------------------------------------------------------------
6  *
7  * Permission is hereby granted, free of charge,
8  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
11  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
16  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 #ifndef __GFX_THUMBNAIL_H
24 #define __GFX_THUMBNAIL_H
25 
26 #include <retro_common_api.h>
27 #include <libretro.h>
28 
29 #include <boolean.h>
30 
31 #include "gfx_animation.h"
32 #include "gfx_thumbnail_path.h"
33 
34 RETRO_BEGIN_DECLS
35 
36 /* Defines the current status of an entry
37  * thumbnail texture */
38 enum gfx_thumbnail_status
39 {
40    GFX_THUMBNAIL_STATUS_UNKNOWN = 0,
41    GFX_THUMBNAIL_STATUS_PENDING,
42    GFX_THUMBNAIL_STATUS_AVAILABLE,
43    GFX_THUMBNAIL_STATUS_MISSING
44 };
45 
46 /* Defines thumbnail alignment within
47  * gfx_thumbnail_draw() bounding box */
48 enum gfx_thumbnail_alignment
49 {
50    GFX_THUMBNAIL_ALIGN_CENTRE = 0,
51    GFX_THUMBNAIL_ALIGN_TOP,
52    GFX_THUMBNAIL_ALIGN_BOTTOM,
53    GFX_THUMBNAIL_ALIGN_LEFT,
54    GFX_THUMBNAIL_ALIGN_RIGHT
55 };
56 
57 /* Defines all possible thumbnail shadow
58  * effect types */
59 enum gfx_thumbnail_shadow_type
60 {
61    GFX_THUMBNAIL_SHADOW_NONE = 0,
62    GFX_THUMBNAIL_SHADOW_DROP,
63    GFX_THUMBNAIL_SHADOW_OUTLINE
64 };
65 
66 /* Holds all runtime parameters associated with
67  * an entry thumbnail */
68 typedef struct
69 {
70    uintptr_t texture;
71    unsigned width;
72    unsigned height;
73    float alpha;
74    float delay_timer;
75    enum gfx_thumbnail_status status;
76    bool fade_active;
77 } gfx_thumbnail_t;
78 
79 /* Holds all configuration parameters associated
80  * with a thumbnail shadow effect */
81 typedef struct
82 {
83    struct
84    {
85       unsigned width;
86    } outline;
87    float alpha;
88    struct
89    {
90       float x_offset;
91       float y_offset;
92    } drop;
93    enum gfx_thumbnail_shadow_type type;
94 } gfx_thumbnail_shadow_t;
95 
96 /* Structure containing all gfx_thumbnail
97  * variables */
98 struct gfx_thumbnail_state
99 {
100    /* Due to the asynchronous nature of thumbnail
101     * loading, it is quite possible to trigger a load
102     * then navigate to a different menu list before
103     * the load is complete/handled. As an additional
104     * safety check, we therefore tag the current menu
105     * list with counter value that is incremented whenever
106     * a list is cleared/set. This is sent as userdata when
107     * requesting a thumbnail, and the upload is only
108     * handled if the tag matches the most recent value
109     * at the time when the load completes */
110    uint64_t list_id;
111 
112    /* When streaming thumbnails, to minimise the processing
113     * of unnecessary images (i.e. when scrolling rapidly through
114     * playlists), we delay loading until an entry has been on screen
115     * for at least gfx_thumbnail_delay ms */
116    float stream_delay;
117 
118    /* Duration in ms of the thumbnail 'fade in' animation */
119    float fade_duration;
120 
121    /* When true, 'fade in' animation will also be
122     * triggered for missing thumbnails */
123    bool fade_missing;
124 };
125 
126 typedef struct gfx_thumbnail_state gfx_thumbnail_state_t;
127 
128 
129 /* Setters */
130 
131 /* When streaming thumbnails, sets time in ms that an
132  * entry must be on screen before an image load is
133  * requested
134  * > if 'delay' is negative, default value is set */
135 void gfx_thumbnail_set_stream_delay(float delay);
136 
137 /* Sets duration in ms of the thumbnail 'fade in'
138  * animation
139  * > If 'duration' is negative, default value is set */
140 void gfx_thumbnail_set_fade_duration(float duration);
141 
142 /* Specifies whether 'fade in' animation should be
143  * triggered for missing thumbnails
144  * > When 'true', allows menu driver to animate
145  *   any 'thumbnail unavailable' notifications */
146 void gfx_thumbnail_set_fade_missing(bool fade_missing);
147 
148 /* Core interface */
149 
150 /* When called, prevents the handling of any pending
151  * thumbnail load requests
152  * >> **MUST** be called before deleting any gfx_thumbnail_t
153  *    objects passed to gfx_thumbnail_request() or
154  *    gfx_thumbnail_process_stream(), otherwise
155  *    heap-use-after-free errors *will* occur */
156 void gfx_thumbnail_cancel_pending_requests(void);
157 
158 /* Requests loading of the specified thumbnail
159  * - If operation fails, 'thumbnail->status' will be set to
160  *   MUI_THUMBNAIL_STATUS_MISSING
161  * - If operation is successful, 'thumbnail->status' will be
162  *   set to MUI_THUMBNAIL_STATUS_PENDING
163  * 'thumbnail' will be populated with texture info/metadata
164  * once the image load is complete
165  * NOTE 1: Must be called *after* gfx_thumbnail_set_system()
166  *         and gfx_thumbnail_set_content*()
167  * NOTE 2: 'playlist' and 'idx' are only required here for
168  *         on-demand thumbnail download support
169  *         (an annoyance...) */
170 void gfx_thumbnail_request(
171       gfx_thumbnail_path_data_t *path_data, enum gfx_thumbnail_id thumbnail_id,
172       playlist_t *playlist, size_t idx, gfx_thumbnail_t *thumbnail,
173       unsigned gfx_thumbnail_upscale_threshold,
174       bool network_on_demand_thumbnails
175       );
176 
177 /* Requests loading of a specific thumbnail image file
178  * (may be used, for example, to load savestate images)
179  * - If operation fails, 'thumbnail->status' will be set to
180  *   MUI_THUMBNAIL_STATUS_MISSING
181  * - If operation is successful, 'thumbnail->status' will be
182  *   set to MUI_THUMBNAIL_STATUS_PENDING
183  * 'thumbnail' will be populated with texture info/metadata
184  * once the image load is complete */
185 void gfx_thumbnail_request_file(
186       const char *file_path, gfx_thumbnail_t *thumbnail,
187       unsigned gfx_thumbnail_upscale_threshold);
188 
189 /* Resets (and free()s the current texture of) the
190  * specified thumbnail */
191 void gfx_thumbnail_reset(gfx_thumbnail_t *thumbnail);
192 
193 /* Stream processing */
194 
195 /* Handles streaming of the specified thumbnail as it moves
196  * on/off screen
197  * - Must be called each frame for every on-screen entry
198  * - Must be called once for each entry as it moves off-screen
199  *   (or can be called each frame - overheads are small)
200  * NOTE 1: Must be called *after* gfx_thumbnail_set_system()
201  * NOTE 2: This function calls gfx_thumbnail_set_content*()
202  * NOTE 3: This function is intended for use in situations
203  *         where each menu entry has a *single* thumbnail.
204  *         If each entry has two thumbnails, use
205  *         gfx_thumbnail_process_streams() for improved
206  *         performance */
207 void gfx_thumbnail_process_stream(
208       gfx_thumbnail_path_data_t *path_data,
209       gfx_animation_t *p_anim,
210       enum gfx_thumbnail_id thumbnail_id,
211       playlist_t *playlist,
212       size_t idx,
213       gfx_thumbnail_t *thumbnail,
214       bool on_screen,
215       unsigned gfx_thumbnail_upscale_threshold,
216       bool network_on_demand_thumbnails
217       );
218 
219 /* Handles streaming of the specified thumbnails as they move
220  * on/off screen
221  * - Must be called each frame for every on-screen entry
222  * - Must be called once for each entry as it moves off-screen
223  *   (or can be called each frame - overheads are small)
224  * NOTE 1: Must be called *after* gfx_thumbnail_set_system()
225  * NOTE 2: This function calls gfx_thumbnail_set_content*()
226  * NOTE 3: This function is intended for use in situations
227  *         where each menu entry has *two* thumbnails.
228  *         If each entry only has a single thumbnail, use
229  *         gfx_thumbnail_process_stream() for improved
230  *         performance */
231 void gfx_thumbnail_process_streams(
232       gfx_thumbnail_path_data_t *path_data,
233       gfx_animation_t *p_anim,
234       playlist_t *playlist, size_t idx,
235       gfx_thumbnail_t *right_thumbnail,
236       gfx_thumbnail_t *left_thumbnail,
237       bool on_screen,
238       unsigned gfx_thumbnail_upscale_threshold,
239       bool network_on_demand_thumbnails
240       );
241 
242 /* Thumbnail rendering */
243 
244 /* Determines the actual screen dimensions of a
245  * thumbnail when centred with aspect correct
246  * scaling within a rectangle of (width x height) */
247 void gfx_thumbnail_get_draw_dimensions(
248       gfx_thumbnail_t *thumbnail,
249       unsigned width, unsigned height, float scale_factor,
250       float *draw_width, float *draw_height);
251 
252 /* Draws specified thumbnail with specified alignment
253  * (and aspect correct scaling) within a rectangle of
254  * (width x height).
255  * 'shadow' defines an optional shadow effect (may be
256  * set to NULL if a shadow effect is not required).
257  * NOTE: Setting scale_factor > 1.0f will increase the
258  *       size of the thumbnail beyond the limits of the
259  *       (width x height) rectangle (alignment + aspect
260  *       correct scaling is preserved). Use with caution */
261 void gfx_thumbnail_draw(
262       void *userdata,
263       unsigned video_width,
264       unsigned video_height,
265       gfx_thumbnail_t *thumbnail,
266       float x, float y, unsigned width, unsigned height,
267       enum gfx_thumbnail_alignment alignment,
268       float alpha, float scale_factor,
269       gfx_thumbnail_shadow_t *shadow);
270 
271 gfx_thumbnail_state_t *gfx_thumb_get_ptr(void);
272 
273 RETRO_END_DECLS
274 
275 #endif
276