1 |
/* |
2 |
* video.h - Video/graphics emulation |
3 |
* |
4 |
* Basilisk II (C) 1997-2008 Christian Bauer |
5 |
* |
6 |
* This program is free software; you can redistribute it and/or modify |
7 |
* it under the terms of the GNU General Public License as published by |
8 |
* the Free Software Foundation; either version 2 of the License, or |
9 |
* (at your option) any later version. |
10 |
* |
11 |
* This program is distributed in the hope that it will be useful, |
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
* GNU General Public License for more details. |
15 |
* |
16 |
* You should have received a copy of the GNU General Public License |
17 |
* along with this program; if not, write to the Free Software |
18 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 |
*/ |
20 |
|
21 |
#ifndef VIDEO_H |
22 |
#define VIDEO_H |
23 |
|
24 |
#include <vector> |
25 |
|
26 |
#ifndef NO_STD_NAMESPACE |
27 |
using std::vector; |
28 |
#endif |
29 |
|
30 |
|
31 |
/* |
32 |
Some of the terminology here is completely frelled. In Basilisk II, a |
33 |
"video mode" refers to a combination of resolution and color depth, and |
34 |
this information is stored in a video_mode structure. In Apple |
35 |
documentation, a "mode" historically refers to the color depth only |
36 |
(because old Macs had fixed-frequency monitors and could not change the |
37 |
resolution). These "modes" are assigned a number (0x80, 0x81, etc.), |
38 |
which we here call "Apple mode". When Macs learned how to deal with |
39 |
multiscan monitors, Apple introduced another type of "mode", also having |
40 |
numbers starting from 0x80 but refrerring to the resolution and/or video |
41 |
timing of the display (it's possible to have two modes with the same |
42 |
dimension but different refresh rates). We call this a "resolution ID". |
43 |
The combination of "Apple mode" and "ID" corresponds to a Basilisk II |
44 |
"video mode". To make the confusion worse, the video driver control call |
45 |
that sets the color depth is called "SetMode" while the one that sets |
46 |
both depth and resolution is "SwitchMode"... |
47 |
*/ |
48 |
|
49 |
// Color depth codes |
50 |
enum video_depth { |
51 |
VDEPTH_1BIT, // 2 colors |
52 |
VDEPTH_2BIT, // 4 colors |
53 |
VDEPTH_4BIT, // 16 colors |
54 |
VDEPTH_8BIT, // 256 colors |
55 |
VDEPTH_16BIT, // "Thousands" |
56 |
VDEPTH_32BIT // "Millions" |
57 |
}; |
58 |
|
59 |
// 1, 2, 4 and 8 bit depths use a color palette |
60 |
inline bool IsDirectMode(video_depth depth) |
61 |
{ |
62 |
return depth == VDEPTH_16BIT || depth == VDEPTH_32BIT; |
63 |
} |
64 |
|
65 |
// Return the depth code that corresponds to the specified bits-per-pixel value |
66 |
inline video_depth DepthModeForPixelDepth(int depth) |
67 |
{ |
68 |
switch (depth) { |
69 |
case 1: return VDEPTH_1BIT; |
70 |
case 2: return VDEPTH_2BIT; |
71 |
case 4: return VDEPTH_4BIT; |
72 |
case 8: return VDEPTH_8BIT; |
73 |
case 15: case 16: return VDEPTH_16BIT; |
74 |
case 24: case 32: return VDEPTH_32BIT; |
75 |
default: return VDEPTH_1BIT; |
76 |
} |
77 |
} |
78 |
|
79 |
// Return a bytes-per-row value (assuming no padding) for the specified depth and pixel width |
80 |
inline uint32 TrivialBytesPerRow(uint32 width, video_depth depth) |
81 |
{ |
82 |
switch (depth) { |
83 |
case VDEPTH_1BIT: return width / 8; |
84 |
case VDEPTH_2BIT: return width / 4; |
85 |
case VDEPTH_4BIT: return width / 2; |
86 |
case VDEPTH_8BIT: return width; |
87 |
case VDEPTH_16BIT: return width * 2; |
88 |
case VDEPTH_32BIT: return width * 4; |
89 |
default: return width; |
90 |
} |
91 |
} |
92 |
|
93 |
|
94 |
/* |
95 |
You are not completely free in your selection of depth/resolution |
96 |
combinations: |
97 |
1) the lowest supported color depth must be available in all |
98 |
resolutions |
99 |
2) if one resolution provides a certain color depth, it must also |
100 |
provide all lower supported depths |
101 |
|
102 |
For example, it is possible to have this set of modes: |
103 |
640x480 @ 8 bit |
104 |
640x480 @ 32 bit |
105 |
800x600 @ 8 bit |
106 |
800x600 @ 32 bit |
107 |
1024x768 @ 8 bit |
108 |
|
109 |
But this is not possible (violates rule 1): |
110 |
640x480 @ 8 bit |
111 |
800x600 @ 8 bit |
112 |
1024x768 @ 1 bit |
113 |
|
114 |
And neither is this (violates rule 2, 640x480 @ 16 bit is missing): |
115 |
640x480 @ 8 bit |
116 |
640x480 @ 32 bit |
117 |
800x600 @ 8 bit |
118 |
800x600 @ 16 bit |
119 |
1024x768 @ 8 bit |
120 |
*/ |
121 |
|
122 |
// Description of a video mode |
123 |
struct video_mode { |
124 |
uint32 x; // X size of screen (pixels) |
125 |
uint32 y; // Y size of screen (pixels) |
126 |
uint32 resolution_id; // Resolution ID (should be >= 0x80 and uniquely identify the sets of modes with the same X/Y size) |
127 |
video_depth depth; // Color depth (see definitions above) |
128 |
uint32 bytes_per_row; // Bytes per row of frame buffer |
129 |
uint32 user_data; // Free for use by platform-specific code |
130 |
}; |
131 |
|
132 |
inline bool IsDirectMode(const video_mode &mode) |
133 |
{ |
134 |
return IsDirectMode(mode.depth); |
135 |
} |
136 |
|
137 |
|
138 |
// Mac video driver per-display private variables (opaque) |
139 |
struct video_locals; |
140 |
|
141 |
|
142 |
// Abstract base class representing one (possibly virtual) monitor |
143 |
// ("monitor" = rectangular display with a contiguous frame buffer) |
144 |
class monitor_desc { |
145 |
public: |
146 |
monitor_desc(const vector<video_mode> &available_modes, video_depth default_depth, uint32 default_id); |
147 |
virtual ~monitor_desc() {} |
148 |
|
149 |
// Get Mac slot ID number |
150 |
uint8 get_slot_id(void) const {return slot_id;} |
151 |
|
152 |
// Get current Mac frame buffer base address |
153 |
uint32 get_mac_frame_base(void) const {return mac_frame_base;} |
154 |
|
155 |
// Set Mac frame buffer base address (called from switch_to_mode()) |
156 |
void set_mac_frame_base(uint32 base) {mac_frame_base = base;} |
157 |
|
158 |
// Get current video mode |
159 |
const video_mode &get_current_mode(void) const {return *current_mode;} |
160 |
|
161 |
// Get Apple mode id for given depth |
162 |
uint16 depth_to_apple_mode(video_depth depth) const {return apple_mode_for_depth[depth];} |
163 |
|
164 |
// Get current color depth |
165 |
uint16 get_apple_mode(void) const {return depth_to_apple_mode(current_mode->depth);} |
166 |
|
167 |
// Get bytes-per-row value for specified resolution/depth |
168 |
// (if the mode isn't supported, make a good guess) |
169 |
uint32 get_bytes_per_row(video_depth depth, uint32 id) const; |
170 |
|
171 |
// Check whether a mode with the specified depth exists on this display |
172 |
bool has_depth(video_depth depth) const; |
173 |
|
174 |
// Mac video driver functions |
175 |
int16 driver_open(void); |
176 |
int16 driver_control(uint16 code, uint32 param, uint32 dce); |
177 |
int16 driver_status(uint16 code, uint32 param); |
178 |
|
179 |
protected: |
180 |
vector<video_mode> modes; // List of supported video modes |
181 |
vector<video_mode>::const_iterator current_mode; // Currently selected video mode |
182 |
|
183 |
uint32 mac_frame_base; // Mac frame buffer address for current mode |
184 |
|
185 |
// Mac video driver per-display private variables/functions |
186 |
private: |
187 |
// Check whether the specified resolution ID is one of the supported resolutions |
188 |
bool has_resolution(uint32 id) const; |
189 |
|
190 |
// Return iterator signifying "invalid mode" |
191 |
vector<video_mode>::const_iterator invalid_mode(void) const {return modes.end();} |
192 |
|
193 |
// Find specified mode (depth/resolution) (or invalid_mode() if not found) |
194 |
vector<video_mode>::const_iterator find_mode(uint16 apple_mode, uint32 id) const; |
195 |
|
196 |
// Find maximum supported depth for given resolution ID |
197 |
video_depth max_depth_of_resolution(uint32 id) const; |
198 |
|
199 |
// Get X/Y size of specified resolution |
200 |
void get_size_of_resolution(uint32 id, uint32 &x, uint32 &y) const; |
201 |
|
202 |
// Set palette to 50% gray |
203 |
void set_gray_palette(void); |
204 |
|
205 |
// Load gamma-corrected black-to-white ramp to palette for direct-color mode |
206 |
void load_ramp_palette(void); |
207 |
|
208 |
// Allocate gamma table of specified size |
209 |
bool allocate_gamma_table(int size); |
210 |
|
211 |
// Set gamma table (0 = build linear ramp) |
212 |
bool set_gamma_table(uint32 user_table); |
213 |
|
214 |
// Switch video mode |
215 |
void switch_mode(vector<video_mode>::const_iterator it, uint32 param, uint32 dce); |
216 |
|
217 |
uint8 slot_id; // NuBus slot ID number |
218 |
static uint8 next_slot_id; // Next available slot ID |
219 |
|
220 |
uint8 palette[256 * 3]; // Color palette, 256 entries, RGB |
221 |
|
222 |
bool luminance_mapping; // Luminance mapping on/off |
223 |
bool interrupts_enabled; // VBL interrupts on/off |
224 |
bool dm_present; // We received a GetVideoParameters call, so the Display Manager seems to be present |
225 |
|
226 |
uint32 gamma_table; // Mac address of gamma table |
227 |
int alloc_gamma_table_size; // Allocated size of gamma table |
228 |
|
229 |
uint16 current_apple_mode; // Currently selected depth/resolution |
230 |
uint32 current_id; |
231 |
uint16 preferred_apple_mode; // Preferred depth/resolution |
232 |
uint32 preferred_id; |
233 |
|
234 |
uint32 slot_param; // Mac address of Slot Manager parameter block |
235 |
|
236 |
// For compatibility reasons with older (pre-Display Manager) versions of |
237 |
// MacOS, the Apple modes must start at 0x80 and be contiguous. Therefore |
238 |
// we maintain an array to map the depth codes to the corresponding Apple |
239 |
// mode. |
240 |
uint16 apple_mode_for_depth[6]; |
241 |
|
242 |
// The following functions are implemented by platform-specific code |
243 |
public: |
244 |
|
245 |
// Called by the video driver to switch the video mode on this display |
246 |
// (must call set_mac_frame_base()) |
247 |
virtual void switch_to_current_mode(void) = 0; |
248 |
|
249 |
// Called by the video driver to set the color palette (in indexed modes) |
250 |
// or the gamma table (in direct modes) |
251 |
virtual void set_palette(uint8 *pal, int num) = 0; |
252 |
}; |
253 |
|
254 |
// Vector of pointers to available monitor descriptions, filled by VideoInit() |
255 |
extern vector<monitor_desc *> VideoMonitors; |
256 |
|
257 |
|
258 |
extern int16 VideoDriverOpen(uint32 pb, uint32 dce); |
259 |
extern int16 VideoDriverControl(uint32 pb, uint32 dce); |
260 |
extern int16 VideoDriverStatus(uint32 pb, uint32 dce); |
261 |
|
262 |
|
263 |
// System specific and internal functions/data |
264 |
extern bool VideoInit(bool classic); |
265 |
extern void VideoExit(void); |
266 |
|
267 |
extern void VideoQuitFullScreen(void); |
268 |
|
269 |
extern void VideoInterrupt(void); |
270 |
extern void VideoRefresh(void); |
271 |
|
272 |
#endif |