summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/rendutil.h
blob: b5c06d6d0fcc06b3a83a2903c4dd9558f60d35be (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    rendutil.h

    Core rendering utilities.

***************************************************************************/

#ifndef MAME_EMU_RENDUTIL_H
#define MAME_EMU_RENDUTIL_H

#pragma once

#include "render.h"

#include <cmath>


/* ----- image formats ----- */

enum ru_imgformat
{
	RENDUTIL_IMGFORMAT_PNG,

	RENDUTIL_IMGFORMAT_UNKNOWN,
	RENDUTIL_IMGFORMAT_ERROR
};



/***************************************************************************
    FUNCTION PROTOTYPES
***************************************************************************/

/* ----- render utilities ----- */

void render_resample_argb_bitmap_hq(bitmap_argb32 &dest, bitmap_argb32 &source, const render_color &color, bool force = false);
bool render_clip_line(render_bounds *bounds, const render_bounds *clip);
bool render_clip_quad(render_bounds *bounds, const render_bounds *clip, render_quad_texuv *texcoords);
void render_line_to_quad(const render_bounds *bounds, float width, float length_extension, render_bounds *bounds0, render_bounds *bounds1);
void render_load_jpeg(bitmap_argb32 &bitmap, emu_file &file, const char *dirname, const char *filename);
bool render_load_png(bitmap_argb32 &bitmap, emu_file &file, const char *dirname, const char *filename, bool load_as_alpha_to_existing = false);
ru_imgformat render_detect_image(emu_file &file, const char *dirname, const char *filename);



/***************************************************************************
    INLINE FUNCTIONS
***************************************************************************/

/*-------------------------------------------------
    render_round_nearest - floating point
    round-to-nearest
-------------------------------------------------*/

static inline float render_round_nearest(float f)
{
	return floor(f + 0.5f);
}


/*-------------------------------------------------
    set_render_bounds_xy - cleaner way to set the
    bounds
-------------------------------------------------*/

static inline void set_render_bounds_xy(render_bounds &bounds, float x0, float y0, float x1, float y1)
{
	bounds.x0 = x0;
	bounds.y0 = y0;
	bounds.x1 = x1;
	bounds.y1 = y1;
}


/*-------------------------------------------------
    set_render_bounds_wh - cleaner way to set the
    bounds
-------------------------------------------------*/

static inline void set_render_bounds_wh(render_bounds &bounds, float x0, float y0, float width, float height)
{
	bounds.x0 = x0;
	bounds.y0 = y0;
	bounds.x1 = x0 + width;
	bounds.y1 = y0 + height;
}


/*-------------------------------------------------
    sect_render_bounds - compute the intersection
    of two render_bounds
-------------------------------------------------*/

static inline void sect_render_bounds(render_bounds &dest, const render_bounds &src)
{
	dest.x0 = (std::max)(dest.x0, src.x0);
	dest.x1 = (std::min)(dest.x1, src.x1);
	dest.y0 = (std::max)(dest.y0, src.y0);
	dest.y1 = (std::min)(dest.y1, src.y1);
}


/*-------------------------------------------------
    union_render_bounds - compute the union of two
    render_bounds
-------------------------------------------------*/

static inline void union_render_bounds(render_bounds &dest, const render_bounds &src)
{
	dest.x0 = (std::min)(dest.x0, src.x0);
	dest.x1 = (std::max)(dest.x1, src.x1);
	dest.y0 = (std::min)(dest.y0, src.y0);
	dest.y1 = (std::max)(dest.y1, src.y1);
}


/*-------------------------------------------------
    set_render_color - cleaner way to set a color
-------------------------------------------------*/

static inline void set_render_color(render_color *color, float a, float r, float g, float b)
{
	color->a = a;
	color->r = r;
	color->g = g;
	color->b = b;
}


/*-------------------------------------------------
    orientation_swap_flips - swap the X and Y
    flip flags
-------------------------------------------------*/

static inline int orientation_swap_flips(int orientation)
{
	return (orientation & ORIENTATION_SWAP_XY) |
			((orientation & ORIENTATION_FLIP_X) ? ORIENTATION_FLIP_Y : 0) |
			((orientation & ORIENTATION_FLIP_Y) ? ORIENTATION_FLIP_X : 0);
}


/*-------------------------------------------------
    orientation_reverse - compute the orientation
    that will undo another orientation
-------------------------------------------------*/

static inline int orientation_reverse(int orientation)
{
	/* if not swapping X/Y, then just apply the same transform to reverse */
	if (!(orientation & ORIENTATION_SWAP_XY))
		return orientation;

	/* if swapping X/Y, then swap X/Y flip bits to get the reverse */
	else
		return orientation_swap_flips(orientation);
}


/*-------------------------------------------------
    orientation_add - compute effective orientation
    after applying two subsequent orientations
-------------------------------------------------*/

static inline int orientation_add(int orientation1, int orientation2)
{
	/* if the 2nd transform doesn't swap, just XOR together */
	if (!(orientation2 & ORIENTATION_SWAP_XY))
		return orientation1 ^ orientation2;

	/* otherwise, we need to effectively swap the flip bits on the first transform */
	else
		return orientation_swap_flips(orientation1) ^ orientation2;
}


/*-------------------------------------------------
    apply_brightness_contrast_gamma_fp - apply
    brightness, contrast, and gamma controls to
    a single RGB component
-------------------------------------------------*/

static inline float apply_brightness_contrast_gamma_fp(float srcval, float brightness, float contrast, float gamma)
{
	/* first apply gamma */
	srcval = pow(srcval, 1.0f / gamma);

	/* then contrast/brightness */
	srcval = (srcval * contrast) + brightness - 1.0f;

	/* clamp and return */
	if (srcval < 0.0f)
		srcval = 0.0f;
	if (srcval > 1.0f)
		srcval = 1.0f;
	return srcval;
}


/*-------------------------------------------------
    apply_brightness_contrast_gamma - apply
    brightness, contrast, and gamma controls to
    a single RGB component
-------------------------------------------------*/

static inline u8 apply_brightness_contrast_gamma(u8 src, float brightness, float contrast, float gamma)
{
	float srcval = (float)src * (1.0f / 255.0f);
	float result = apply_brightness_contrast_gamma_fp(srcval, brightness, contrast, gamma);
	return u8(result * 255.0f);
}


#endif // MAME_EMU_RENDUTIL_H