AllegroGL  0.4.4
scorer.c
Go to the documentation of this file.
1 /* This code is (C) AllegroGL contributors, and double licensed under
2  * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
3  */
8 #include <allegro.h>
9 
10 #include "alleggl.h"
11 #include "allglint.h"
12 
13 
14 static int best, best_score;
15 
16 
17 #define target allegro_gl_display_info
18 #define req __allegro_gl_required_settings
19 #define sug __allegro_gl_suggested_settings
20 
21 #define PREFIX_I "agl-scorer INFO: "
22 
23 
24 /* __allegro_gl_fill_in_info()
25  * Will fill in missing settings by 'guessing'
26  * what the user intended.
27  */
28 void __allegro_gl_fill_in_info() {
29 
30  int all_components = AGL_RED_DEPTH | AGL_GREEN_DEPTH | AGL_BLUE_DEPTH
32 
33  /* If all color components were set, but not the color depth */
34  if ((((req | sug) & AGL_COLOR_DEPTH) == 0)
35  && (((req | sug) & all_components) == all_components)) {
36 
37  target.colour_depth = target.pixel_size.rgba.r
38  + target.pixel_size.rgba.g
39  + target.pixel_size.rgba.b
40  + target.pixel_size.rgba.a;
41 
42  /* Round depth to 8 bits */
43  target.colour_depth = (target.colour_depth + 7) / 8;
44  }
45  /* If only some components were set, guess the others */
46  else if ((req | sug) & all_components) {
47 
48  int avg = ((req | sug) & AGL_RED_DEPTH ? target.pixel_size.rgba.r: 0)
49  + ((req | sug) & AGL_GREEN_DEPTH ? target.pixel_size.rgba.g: 0)
50  + ((req | sug) & AGL_BLUE_DEPTH ? target.pixel_size.rgba.b: 0)
51  + ((req | sug) & AGL_ALPHA_DEPTH ? target.pixel_size.rgba.a: 0);
52 
53  int num = ((req | sug) & AGL_RED_DEPTH ? 1 : 0)
54  + ((req | sug) & AGL_GREEN_DEPTH ? 1 : 0)
55  + ((req | sug) & AGL_BLUE_DEPTH ? 1 : 0)
56  + ((req | sug) & AGL_ALPHA_DEPTH ? 1 : 0);
57 
58  avg /= (num ? num : 1);
59 
60  if (((req | sug) & AGL_RED_DEPTH )== 0) {
61  sug |= AGL_RED_DEPTH;
62  target.pixel_size.rgba.r = avg;
63  }
64  if (((req | sug) & AGL_GREEN_DEPTH) == 0) {
65  sug |= AGL_GREEN_DEPTH;
66  target.pixel_size.rgba.g = avg;
67  }
68  if (((req | sug) & AGL_BLUE_DEPTH) == 0) {
69  sug |= AGL_BLUE_DEPTH;
70  target.pixel_size.rgba.b = avg;
71  }
72  if (((req | sug) & AGL_ALPHA_DEPTH) == 0) {
73  sug |= AGL_ALPHA_DEPTH;
74  target.pixel_size.rgba.a = avg;
75  }
76 
77  /* If color depth wasn't defined, figure it out */
78  if (((req | sug) & AGL_COLOR_DEPTH) == 0) {
79  __allegro_gl_fill_in_info();
80  }
81  }
82 
83  /* If the user forgot to set a color depth in AGL, but used the
84  * Allegro one instead
85  */
86  if ((((req | sug) & AGL_COLOR_DEPTH) == 0) && (target.colour_depth == 0)) {
87  BITMAP *temp = create_bitmap(1, 1);
88  if (temp) {
89  allegro_gl_set(AGL_COLOR_DEPTH, bitmap_color_depth(temp));
90  allegro_gl_set(AGL_REQUIRE, AGL_COLOR_DEPTH);
91  destroy_bitmap(temp);
92  }
93  }
94 
95 
96  /* Prefer double-buffering */
97  if (!((req | sug) & AGL_DOUBLEBUFFER)) {
98  allegro_gl_set(AGL_DOUBLEBUFFER, 1);
99  allegro_gl_set(AGL_SUGGEST, AGL_DOUBLEBUFFER);
100  }
101 
102  /* Prefer no multisamping */
103  if (!((req | sug) & (AGL_SAMPLE_BUFFERS | AGL_SAMPLES))) {
107  }
108 
109  /* Prefer monoscopic */
110  if (!((req | sug) & AGL_STEREO)) {
111  allegro_gl_set(AGL_STEREO, 0);
112  allegro_gl_set(AGL_SUGGEST, AGL_STEREO);
113  }
114 
115  /* Prefer unsigned normalized buffers */
116  if (!((req | sug) & (AGL_FLOAT_COLOR | AGL_FLOAT_Z))) {
120  }
121 }
122 
123 
124 
125 void __allegro_gl_reset_scorer(void)
126 {
127  best = -1;
128  best_score = -1;
129 }
130 
131 
132 
133 static int get_score(struct allegro_gl_display_info *dinfo)
134 {
135  int score = 0;
136 
137  if (dinfo->colour_depth != target.colour_depth) {
138  if (req & AGL_COLOR_DEPTH) {
139  ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
140  get_config_text("Color depth requirement not met."));
141  return -1;
142  }
143  }
144  else {
145  /* If requested color depths agree */
146  score += 128;
147  }
148 
149 
150  if (sug & AGL_COLOR_DEPTH) {
151  if (dinfo->colour_depth < target.colour_depth)
152  score += (96 * dinfo->colour_depth) / target.colour_depth;
153  else
154  score += 96 + 96 / (1 + dinfo->colour_depth - target.colour_depth);
155  }
156 
157 
158  /* check colour component widths here and Allegro formatness */
159  if ((req & AGL_RED_DEPTH)
160  && (dinfo->pixel_size.rgba.r != target.pixel_size.rgba.r)) {
161 
162  ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
163  get_config_text("Red depth requirement not met."));
164  return -1;
165  }
166 
167  if (sug & AGL_RED_DEPTH) {
168  if (dinfo->pixel_size.rgba.r < target.pixel_size.rgba.r) {
169  score += (16 * dinfo->pixel_size.rgba.r) / target.pixel_size.rgba.r;
170  }
171  else {
172  score += 16
173  + 16 / (1 + dinfo->pixel_size.rgba.r - target.pixel_size.rgba.r);
174  }
175  }
176 
177  if ((req & AGL_GREEN_DEPTH)
178  && (dinfo->pixel_size.rgba.g != target.pixel_size.rgba.g)) {
179 
180  ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
181  get_config_text("Green depth requirement not met."));
182  return -1;
183  }
184 
185  if (sug & AGL_GREEN_DEPTH) {
186  if (dinfo->pixel_size.rgba.g < target.pixel_size.rgba.g) {
187  score += (16 * dinfo->pixel_size.rgba.g) / target.pixel_size.rgba.g;
188  }
189  else {
190  score += 16
191  + 16 / (1 + dinfo->pixel_size.rgba.g - target.pixel_size.rgba.g);
192  }
193  }
194 
195  if ((req & AGL_BLUE_DEPTH)
196  && (dinfo->pixel_size.rgba.b != target.pixel_size.rgba.b)) {
197 
198  ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
199  get_config_text("Blue depth requirement not met."));
200  return -1;
201  }
202 
203  if (sug & AGL_BLUE_DEPTH) {
204  if (dinfo->pixel_size.rgba.b < target.pixel_size.rgba.b) {
205  score += (16 * dinfo->pixel_size.rgba.b) / target.pixel_size.rgba.b;
206  }
207  else {
208  score += 16
209  + 16 / (1 + dinfo->pixel_size.rgba.b - target.pixel_size.rgba.b);
210  }
211  }
212 
213  if ((req & AGL_ALPHA_DEPTH)
214  && (dinfo->pixel_size.rgba.a != target.pixel_size.rgba.a)) {
215 
216  ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
217  get_config_text("Alpha depth requirement not met."));
218  return -1;
219  }
220 
221  if (sug & AGL_ALPHA_DEPTH) {
222  if (dinfo->pixel_size.rgba.a < target.pixel_size.rgba.a) {
223  score += (16 * dinfo->pixel_size.rgba.a) / target.pixel_size.rgba.a;
224  }
225  else {
226  score += 16
227  + 16 / (1 + dinfo->pixel_size.rgba.a - target.pixel_size.rgba.a);
228  }
229  }
230 
231 
232  if ((req & AGL_ACC_RED_DEPTH)
233  && (dinfo->accum_size.rgba.r != target.accum_size.rgba.r)) {
234 
235  ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
236  get_config_text("Accumulator Red depth requirement not met."));
237  return -1;
238  }
239 
240  if (sug & AGL_ACC_RED_DEPTH) {
241  if (dinfo->accum_size.rgba.r < target.accum_size.rgba.r) {
242  score += (16 * dinfo->accum_size.rgba.r) / target.accum_size.rgba.r;
243  }
244  else {
245  score += 16
246  + 16 / (1 + dinfo->accum_size.rgba.r - target.accum_size.rgba.r);
247  }
248  }
249 
250  if ((req & AGL_ACC_GREEN_DEPTH)
251  && (dinfo->accum_size.rgba.g != target.accum_size.rgba.g)) {
252 
253  ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
254  get_config_text("Accumulator Green depth requirement not met."));
255  return -1;
256  }
257 
258  if (sug & AGL_ACC_GREEN_DEPTH) {
259  if (dinfo->accum_size.rgba.g < target.accum_size.rgba.g) {
260  score += (16 * dinfo->accum_size.rgba.g) / target.accum_size.rgba.g;
261  }
262  else {
263  score += 16
264  + 16 / (1 + dinfo->accum_size.rgba.g - target.accum_size.rgba.g);
265  }
266  }
267 
268  if ((req & AGL_ACC_BLUE_DEPTH)
269  && (dinfo->accum_size.rgba.b != target.accum_size.rgba.b)) {
270 
271  ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
272  get_config_text("Accumulator Blue depth requirement not met."));
273  return -1;
274  }
275 
276  if (sug & AGL_ACC_BLUE_DEPTH) {
277  if (dinfo->accum_size.rgba.b < target.accum_size.rgba.b) {
278  score += (16 * dinfo->accum_size.rgba.b) / target.accum_size.rgba.b;
279  }
280  else {
281  score += 16
282  + 16 / (1 + dinfo->accum_size.rgba.b - target.accum_size.rgba.b);
283  }
284  }
285 
286  if ((req & AGL_ACC_ALPHA_DEPTH)
287  && (dinfo->accum_size.rgba.a != target.accum_size.rgba.a)) {
288 
289  ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
290  get_config_text("Accumulator Alpha depth requirement not met."));
291  return -1;
292  }
293 
294  if (sug & AGL_ACC_ALPHA_DEPTH) {
295  if (dinfo->accum_size.rgba.a < target.accum_size.rgba.a) {
296  score += (16 * dinfo->accum_size.rgba.a) / target.accum_size.rgba.a;
297  }
298  else {
299  score += 16
300  + 16 / (1 + dinfo->accum_size.rgba.a - target.accum_size.rgba.a);
301  }
302  }
303 
304 
305 
306  if (!dinfo->doublebuffered != !target.doublebuffered) {
307  if (req & AGL_DOUBLEBUFFER) {
308  ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
309  get_config_text("Double Buffer requirement not met."));
310  return -1;
311  }
312  }
313  else {
314  score += (sug & AGL_DOUBLEBUFFER) ? 256 : 1;
315  }
316 
317  if (!dinfo->stereo != !target.stereo) {
318  if (req & AGL_STEREO) {
319  ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
320  get_config_text("Stereo Buffer requirement not met."));
321  return -1;
322  }
323  }
324  else {
325  if (sug & AGL_STEREO) {
326  score += 128;
327  }
328  }
329 
330  if ((req & AGL_AUX_BUFFERS) && (dinfo->aux_buffers < target.aux_buffers)) {
331  ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
332  get_config_text("Aux Buffer requirement not met."));
333  return -1;
334  }
335 
336  if (sug & AGL_AUX_BUFFERS) {
337  if (dinfo->aux_buffers < target.aux_buffers) {
338  score += (64 * dinfo->aux_buffers) / target.aux_buffers;
339  }
340  else {
341  score += 64 + 64 / (1 + dinfo->aux_buffers - target.aux_buffers);
342  }
343  }
344 
345  if ((req & AGL_Z_DEPTH) && (dinfo->depth_size != target.depth_size)) {
346  ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
347  get_config_text("Z-Buffer requirement not met."));
348  return -1;
349  }
350  if (sug & AGL_Z_DEPTH) {
351  if (dinfo->depth_size < target.depth_size) {
352  score += (64 * dinfo->depth_size) / target.depth_size;
353  }
354  else {
355  score += 64 + 64 / (1 + dinfo->depth_size - target.depth_size);
356  }
357  }
358 
359  if ((req & AGL_STENCIL_DEPTH)
360  && (dinfo->stencil_size != target.stencil_size)) {
361 
362  ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
363  get_config_text("Stencil depth requirement not met."));
364  return -1;
365  }
366 
367  if (sug & AGL_STENCIL_DEPTH) {
368  if (dinfo->stencil_size < target.stencil_size) {
369  score += (64 * dinfo->stencil_size) / target.stencil_size;
370  }
371  else {
372  score += 64 + 64 / (1 + dinfo->stencil_size - target.stencil_size);
373  }
374  }
375 
376  if ((req & AGL_RENDERMETHOD)
377  && ((dinfo->rmethod != target.rmethod) || (target.rmethod == 2))) {
378 
379  ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
380  get_config_text("Render Method requirement not met"));
381  return -1;
382  }
383 
384  if ((sug & AGL_RENDERMETHOD) && (dinfo->rmethod == target.rmethod)) {
385  score += 1024;
386  }
387  else if (dinfo->rmethod == 1) {
388  score++; /* Add 1 for h/w accel */
389  }
390 
391  if ((req & AGL_SAMPLE_BUFFERS)
392  && (dinfo->sample_buffers != target.sample_buffers)) {
393  ustrzcpy(allegro_gl_error, AGL_ERROR_SIZE,
394  get_config_text("Multisample Buffers requirement not met"));
395  return -1;
396  }
397 
398  if (sug & AGL_SAMPLE_BUFFERS) {
399  if (dinfo->sample_buffers < target.sample_buffers) {
400  score += (64 * dinfo->sample_buffers) / target.sample_buffers;
401  }
402  else {
403  score += 64
404  + 64 / (1 + dinfo->sample_buffers - target.sample_buffers);
405  }
406  }
407 
408  if ((req & AGL_SAMPLES) && (dinfo->samples != target.samples)) {
409  ustrzcpy(allegro_gl_error, AGL_ERROR_SIZE,
410  get_config_text("Multisample Samples requirement not met"));
411  return -1;
412  }
413 
414  if (sug & AGL_SAMPLES) {
415  if (dinfo->samples < target.samples) {
416  score += (64 * dinfo->samples) / target.samples;
417  }
418  else {
419  score += 64 + 64 / (1 + dinfo->samples - target.samples);
420  }
421  }
422 
423 
424  if (!dinfo->float_color != !target.float_color) {
425  if (req & AGL_FLOAT_COLOR) {
426  ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
427  get_config_text("Float Color requirement not met."));
428  return -1;
429  }
430  }
431  else {
432  if (sug & AGL_FLOAT_COLOR) {
433  score += 128;
434  }
435  }
436 
437  if (!dinfo->float_depth != !target.float_depth) {
438  if (req & AGL_FLOAT_Z) {
439  ustrzcpy (allegro_gl_error, AGL_ERROR_SIZE,
440  get_config_text("Float Depth requirement not met."));
441  return -1;
442  }
443  }
444  else {
445  if (sug & AGL_FLOAT_Z) {
446  score += 128;
447  }
448  }
449 
450  TRACE(PREFIX_I "Score is : %i\n", score);
451  return score;
452 }
453 
454 #undef target
455 #undef req
456 #undef sug
457 
458 
459 
460 int __allegro_gl_score_config(int refnum,
461  struct allegro_gl_display_info *dinfo)
462 {
463  int score = get_score(dinfo);
464  if (score == -1) {
465  TRACE(PREFIX_I "score_config: %s\n", allegro_gl_error);
466  return score;
467  }
468 
469  if (score == best_score) {
470  /*
471  TRACE(PREFIX_I "score_config: score == best_score, should we change "
472  "scoring algorithm?\n");
473  */
474  }
475 
476  if (score > best_score) {
477  best_score = score;
478  best = refnum;
479  }
480 
481  return score;
482 }
483 
484 
485 
486 int __allegro_gl_best_config(void)
487 {
488  return best;
489 }
490 
#define AGL_SAMPLE_BUFFERS
Define multisample parameters Some OpenGL ICDs expose an extension called GL_ARB_multisample which pr...
Definition: alleggl.h:361
#define AGL_GREEN_DEPTH
Select the green depth of the frame buffer.
Definition: alleggl.h:205
#define AGL_STEREO
Creates seperate left/right buffers for stereo display.
Definition: alleggl.h:269
#define AGL_REQUIRE
Reject other values for these settings.
Definition: alleggl.h:393
#define AGL_DOUBLEBUFFER
Creates a backbuffer if set.
Definition: alleggl.h:260
#define AGL_ALPHA_DEPTH
Select the alpha depth of the frame buffer.
Definition: alleggl.h:218
#define AGL_SUGGEST
Prefer the assigned values for these settings.
Definition: alleggl.h:392
#define AGL_SAMPLES
Define multisample samples Set this value to the number of samples that can be accepted in the multis...
Definition: alleggl.h:369
#define AGL_ACC_BLUE_DEPTH
Select the blue depth of the accumulator buffer.
Definition: alleggl.h:246
#define AGL_ACC_ALPHA_DEPTH
Select the alpha depth of the accumulator buffer.
Definition: alleggl.h:254
#define AGL_ACC_GREEN_DEPTH
Select the green depth of the accumulator buffer.
Definition: alleggl.h:238
void allegro_gl_set(int option, int value)
Sets a configuration option.
Definition: alleggl.c:274
#define AGL_Z_DEPTH
Select the depth of the z-buffer.
Definition: alleggl.h:282
#define AGL_STENCIL_DEPTH
Select the depth of the stencil buffer.
Definition: alleggl.h:291
#define AGL_FLOAT_COLOR
Floating-point Color buffer.
Definition: alleggl.h:375
#define AGL_COLOR_DEPTH
Specify the total color depth of the frame buffer.
Definition: alleggl.h:223
#define AGL_FLOAT_Z
Floating-point Depth buffer.
Definition: alleggl.h:379
#define AGL_AUX_BUFFERS
Creates additional auxiliary buffers.
Definition: alleggl.h:275
#define AGL_ACC_RED_DEPTH
Select the red depth of the accumulator buffer.
Definition: alleggl.h:231
Main header file for AllegroGL.
#define AGL_BLUE_DEPTH
Select the blue depth of the frame buffer.
Definition: alleggl.h:211
#define AGL_RED_DEPTH
Select the red depth of the frame buffer.
Definition: alleggl.h:199
#define AGL_RENDERMETHOD
Set it if you&#39;d like AllegroGL to pay special attention on whether hardware acceleration is present o...
Definition: alleggl.h:310