1 #include "d3d.h"
2
3 ALLEGRO_DEBUG_CHANNEL("d3d")
4
5 struct DEPTH_STENCIL_DESC {
6 int d;
7 int s;
8 D3DFORMAT format;
9 };
10
11 static DEPTH_STENCIL_DESC depth_stencil_formats[] = {
12 { 0, 0, (D3DFORMAT)0 },
13 { 32, 0, D3DFMT_D32 },
14 { 15, 1, D3DFMT_D15S1 },
15 { 24, 8, D3DFMT_D24S8 },
16 { 24, 0, D3DFMT_D24X8 },
17 { 24, 4, D3DFMT_D24X4S4 },
18 { 16, 0, D3DFMT_D16 },
19 };
20
IsDepthFormatExisting(D3DFORMAT DepthFormat,D3DFORMAT AdapterFormat)21 static BOOL IsDepthFormatExisting(D3DFORMAT DepthFormat, D3DFORMAT AdapterFormat)
22 {
23 HRESULT hr = _al_d3d->CheckDeviceFormat(D3DADAPTER_DEFAULT,
24 D3DDEVTYPE_HAL,
25 AdapterFormat,
26 D3DUSAGE_DEPTHSTENCIL,
27 D3DRTYPE_SURFACE,
28 DepthFormat);
29
30 return SUCCEEDED(hr);
31 }
32
33 static const int D3D_DEPTH_FORMATS = sizeof(depth_stencil_formats) / sizeof(*depth_stencil_formats);
34
35 static _AL_VECTOR eds_list;
36
_al_d3d_destroy_display_format_list(void)37 void _al_d3d_destroy_display_format_list(void)
38 {
39 /* Free the display format list */
40 for (int j = 0; j < (int)_al_vector_size(&eds_list); j++) {
41 void **eds = (void **)_al_vector_ref(&eds_list, j);
42 al_free(*eds);
43 }
44 _al_vector_free(&eds_list);
45 }
46
_al_d3d_generate_display_format_list(void)47 void _al_d3d_generate_display_format_list(void)
48 {
49 static bool fullscreen = !(al_get_new_display_flags() & ALLEGRO_FULLSCREEN); /* stop warning */
50 static int adapter = ~al_get_new_display_adapter(); /* stop warning */
51 int i;
52
53 if (!_al_vector_is_empty(&eds_list) && (fullscreen == (bool)(al_get_new_display_flags() & ALLEGRO_FULLSCREEN))
54 && (adapter == al_get_new_display_adapter())) {
55 return;
56 }
57 else if (!_al_vector_is_empty(&eds_list)) {
58 _al_d3d_destroy_display_format_list();
59 }
60
61 fullscreen = (al_get_new_display_flags() & ALLEGRO_FULLSCREEN) != 0;
62 adapter = al_get_new_display_adapter();
63 if (adapter < 0)
64 adapter = 0;
65
66 _al_vector_init(&eds_list, sizeof(ALLEGRO_EXTRA_DISPLAY_SETTINGS *));
67
68 /* Loop through each bit combination of:
69 * bit 0: 16/32 bit
70 * bit 1: single-buffer
71 * bit 2: vsync
72 */
73 for (i = 0; i < 8; i++) {
74 int format_num = !!(i & 1);
75 int single_buffer = !!(i & 2);
76 int vsync = !!(i & 4);
77 int allegro_format = ALLEGRO_PIXEL_FORMAT_XRGB_8888;
78 if (format_num == 1) allegro_format = ALLEGRO_PIXEL_FORMAT_RGB_565;
79 D3DFORMAT d3d_format = (D3DFORMAT)_al_pixel_format_to_d3d(allegro_format);
80
81 /* Count available multisample quality levels. */
82 DWORD quality_levels = 0;
83
84 if (_al_d3d->CheckDeviceMultiSampleType(adapter, D3DDEVTYPE_HAL, d3d_format,
85 !fullscreen, D3DMULTISAMPLE_NONMASKABLE, &quality_levels) != D3D_OK) {
86 _al_d3d->CheckDeviceMultiSampleType(adapter, D3DDEVTYPE_REF, d3d_format,
87 !fullscreen, D3DMULTISAMPLE_NONMASKABLE, &quality_levels);
88 }
89
90 /* Loop through available depth/stencil formats. */
91 for (int j = 0; j < D3D_DEPTH_FORMATS; j++) {
92 if (j == 0 || IsDepthFormatExisting(
93 depth_stencil_formats[j].format, d3d_format)) {
94 DEPTH_STENCIL_DESC *ds = depth_stencil_formats + j;
95 for (int k = 0; k < (int)quality_levels + 1; k++) {
96 ALLEGRO_EXTRA_DISPLAY_SETTINGS *eds, **peds;
97 peds = (ALLEGRO_EXTRA_DISPLAY_SETTINGS **)_al_vector_alloc_back(&eds_list);
98 eds = *peds = (ALLEGRO_EXTRA_DISPLAY_SETTINGS *)al_malloc(sizeof *eds);
99 memset(eds->settings, 0, sizeof(int) * ALLEGRO_DISPLAY_OPTIONS_COUNT);
100
101 eds->settings[ALLEGRO_COMPATIBLE_DISPLAY] = 1;
102
103 if (format_num == 0) {
104 eds->settings[ALLEGRO_RED_SIZE] = 8;
105 eds->settings[ALLEGRO_GREEN_SIZE] = 8;
106 eds->settings[ALLEGRO_BLUE_SIZE] = 8;
107 eds->settings[ALLEGRO_RED_SHIFT] = 16;
108 eds->settings[ALLEGRO_GREEN_SHIFT] = 8;
109 eds->settings[ALLEGRO_BLUE_SHIFT] = 0;
110 eds->settings[ALLEGRO_COLOR_SIZE] = 32;
111 }
112 else if (format_num == 1) {
113 eds->settings[ALLEGRO_RED_SIZE] = 5;
114 eds->settings[ALLEGRO_GREEN_SIZE] = 6;
115 eds->settings[ALLEGRO_BLUE_SIZE] = 5;
116 eds->settings[ALLEGRO_RED_SHIFT] = 11;
117 eds->settings[ALLEGRO_GREEN_SHIFT] = 5;
118 eds->settings[ALLEGRO_BLUE_SHIFT] = 0;
119 eds->settings[ALLEGRO_COLOR_SIZE] = 16;
120 }
121
122 if (single_buffer) {
123 eds->settings[ALLEGRO_SINGLE_BUFFER] = 1;
124 eds->settings[ALLEGRO_UPDATE_DISPLAY_REGION] = 1;
125 }
126
127 if (vsync) {
128 eds->settings[ALLEGRO_VSYNC] = 1;
129 }
130
131 eds->settings[ALLEGRO_DEPTH_SIZE] = ds->d;
132 eds->settings[ALLEGRO_STENCIL_SIZE] = ds->s;
133
134 if (k > 1) {
135 eds->settings[ALLEGRO_SAMPLE_BUFFERS] = 1;
136 // TODO: Is it ok to use the quality level here?
137 eds->settings[ALLEGRO_SAMPLES] = k;
138 }
139 }
140 }
141 }
142
143 }
144 ALLEGRO_INFO("found %d format combinations\n", _al_vector_size(&eds_list));
145 }
146
_al_d3d_score_display_settings(ALLEGRO_EXTRA_DISPLAY_SETTINGS * ref)147 void _al_d3d_score_display_settings(ALLEGRO_EXTRA_DISPLAY_SETTINGS *ref)
148 {
149 for (int i = 0; i < (int)_al_vector_size(&eds_list); i++) {
150 ALLEGRO_EXTRA_DISPLAY_SETTINGS *eds, **peds;
151 peds = (ALLEGRO_EXTRA_DISPLAY_SETTINGS **)_al_vector_ref(&eds_list, i);
152 eds = *peds;
153 eds->score = _al_score_display_settings(eds, ref);
154 eds->index = i;
155 }
156
157 qsort(eds_list._items, eds_list._size, eds_list._itemsize, _al_display_settings_sorter);
158 }
159
160 /* Helper function for sorting pixel formats by index */
d3d_display_list_resorter(const void * p0,const void * p1)161 static int d3d_display_list_resorter(const void *p0, const void *p1)
162 {
163 const ALLEGRO_EXTRA_DISPLAY_SETTINGS *f0 = *((ALLEGRO_EXTRA_DISPLAY_SETTINGS **)p0);
164 const ALLEGRO_EXTRA_DISPLAY_SETTINGS *f1 = *((ALLEGRO_EXTRA_DISPLAY_SETTINGS **)p1);
165
166 if (!f0)
167 return 1;
168 if (!f1)
169 return -1;
170 if (f0->index == f1->index) {
171 return 0;
172 }
173 else if (f0->index < f1->index) {
174 return -1;
175 }
176 else {
177 return 1;
178 }
179 }
180
_al_d3d_resort_display_settings(void)181 void _al_d3d_resort_display_settings(void)
182 {
183 qsort(eds_list._items, eds_list._size, eds_list._itemsize, d3d_display_list_resorter);
184 }
185
_al_d3d_get_display_settings(int i)186 ALLEGRO_EXTRA_DISPLAY_SETTINGS *_al_d3d_get_display_settings(int i)
187 {
188 if (i < (int)_al_vector_size(&eds_list))
189 return *(ALLEGRO_EXTRA_DISPLAY_SETTINGS **)_al_vector_ref(&eds_list, i);
190 return NULL;
191 }
192