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