1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * Thread local storage.
12 *
13 * By Trent Gamblin.
14 *
15 */
16
17 /* FIXME:
18 *
19 * There are several ways to get thread local storage:
20 *
21 * 1. pthreads.
22 * 2. __thread keyword in gcc.
23 * 3. __declspec(thread) in MSVC.
24 * 4. TLS API under Windows.
25 *
26 * Since pthreads is available from the system everywhere except in
27 * Windows, this is the only case which is problematic. It appears
28 * that except for old mingw versions (before gcc 4.2) we can simply
29 * use __thread, and for MSVC we can always use __declspec(thread):
30 *
31 * However there also is a WANT_TLS configuration variable which is on
32 * by default and forces use of the TLS API instead. At the same time,
33 * the implementation using the TLS API in this file does not work
34 * with static linking. Someone should either completely remove
35 * WANT_TLS, or fix the static linking case...
36 */
37
38 #include <string.h>
39 #include "allegro5/allegro.h"
40 #include "allegro5/internal/aintern.h"
41 #include "allegro5/internal/aintern_bitmap.h"
42 #include "allegro5/internal/aintern_display.h"
43 #include "allegro5/internal/aintern_file.h"
44 #include "allegro5/internal/aintern_fshook.h"
45 #include "allegro5/internal/aintern_shader.h"
46 #include "allegro5/internal/aintern_tls.h"
47
48 #ifdef ALLEGRO_ANDROID
49 #include "allegro5/internal/aintern_android.h"
50 #endif
51
52 #if defined(ALLEGRO_MINGW32) && !defined(ALLEGRO_CFG_DLL_TLS)
53 /*
54 * MinGW < 4.2.1 doesn't have builtin thread local storage, so we
55 * must use the Windows API.
56 */
57 #if __GNUC__ < 4
58 #define ALLEGRO_CFG_DLL_TLS
59 #elif __GNUC__ == 4 && __GNUC_MINOR__ < 2
60 #define ALLEGRO_CFG_DLL_TLS
61 #elif __GNUC__ == 4 && __GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ < 1
62 #define ALLEGRO_CFG_DLL_TLS
63 #endif
64 #endif
65
66
67 /* Thread local storage for various per-thread state. */
68 typedef struct thread_local_state {
69 /* New display parameters */
70 int new_display_flags;
71 int new_display_refresh_rate;
72 int new_display_adapter;
73 int new_window_x;
74 int new_window_y;
75 int new_bitmap_depth;
76 int new_bitmap_samples;
77 ALLEGRO_EXTRA_DISPLAY_SETTINGS new_display_settings;
78
79 /* Current display */
80 ALLEGRO_DISPLAY *current_display;
81
82 /* Target bitmap */
83 ALLEGRO_BITMAP *target_bitmap;
84
85 /* Blender */
86 ALLEGRO_BLENDER current_blender;
87
88 /* Bitmap parameters */
89 int new_bitmap_format;
90 int new_bitmap_flags;
91
92 /* Files */
93 const ALLEGRO_FILE_INTERFACE *new_file_interface;
94 const ALLEGRO_FS_INTERFACE *fs_interface;
95
96 /* Error code */
97 int allegro_errno;
98
99 /* Title to use for a new window/display.
100 * This is a static buffer for API reasons.
101 */
102 char new_window_title[ALLEGRO_NEW_WINDOW_TITLE_MAX_SIZE + 1];
103
104 #ifdef ALLEGRO_ANDROID
105 JNIEnv *jnienv;
106 #endif
107
108 /* Destructor ownership count */
109 int dtor_owner_count;
110 } thread_local_state;
111
112
113 typedef struct INTERNAL_STATE {
114 thread_local_state tls;
115 ALLEGRO_BLENDER stored_blender;
116 ALLEGRO_TRANSFORM stored_transform;
117 ALLEGRO_TRANSFORM stored_projection_transform;
118 int flags;
119 } INTERNAL_STATE;
120
121 ALLEGRO_STATIC_ASSERT(tls, sizeof(ALLEGRO_STATE) > sizeof(INTERNAL_STATE));
122
123
initialize_blender(ALLEGRO_BLENDER * b)124 static void initialize_blender(ALLEGRO_BLENDER *b)
125 {
126 b->blend_op = ALLEGRO_ADD;
127 b->blend_source = ALLEGRO_ONE,
128 b->blend_dest = ALLEGRO_INVERSE_ALPHA;
129 b->blend_alpha_op = ALLEGRO_ADD;
130 b->blend_alpha_source = ALLEGRO_ONE;
131 b->blend_alpha_dest = ALLEGRO_INVERSE_ALPHA;
132 b->blend_color = al_map_rgba_f(1.0f, 1.0f, 1.0f, 1.0f);
133 }
134
135
initialize_tls_values(thread_local_state * tls)136 static void initialize_tls_values(thread_local_state *tls)
137 {
138 memset(tls, 0, sizeof *tls);
139
140 tls->new_display_adapter = ALLEGRO_DEFAULT_DISPLAY_ADAPTER;
141 tls->new_window_x = INT_MAX;
142 tls->new_window_y = INT_MAX;
143
144 initialize_blender(&tls->current_blender);
145 tls->new_bitmap_flags = ALLEGRO_CONVERT_BITMAP;
146 tls->new_bitmap_format = ALLEGRO_PIXEL_FORMAT_ANY_WITH_ALPHA;
147 tls->new_file_interface = &_al_file_interface_stdio;
148 tls->fs_interface = &_al_fs_interface_stdio;
149 memset(tls->new_window_title, 0, ALLEGRO_NEW_WINDOW_TITLE_MAX_SIZE + 1);
150
151 _al_fill_display_settings(&tls->new_display_settings);
152 }
153
154 // FIXME: The TLS implementation below only works for dynamic linking
155 // right now - instead of using DllMain we should simply initialize
156 // on first request.
157 #ifdef ALLEGRO_STATICLINK
158 #undef ALLEGRO_CFG_DLL_TLS
159 #endif
160
161 #if defined(ALLEGRO_CFG_DLL_TLS)
162 #include "tls_dll.inc"
163 #elif defined(ALLEGRO_MACOSX) || defined(ALLEGRO_IPHONE) || defined(ALLEGRO_ANDROID) || defined(ALLEGRO_RASPBERRYPI)
164 #include "tls_pthread.inc"
165 #else
166 #include "tls_native.inc"
167 #endif
168
169
170
_al_reinitialize_tls_values(void)171 void _al_reinitialize_tls_values(void)
172 {
173 thread_local_state *tls;
174 if ((tls = tls_get()) == NULL)
175 return;
176 initialize_tls_values(tls);
177 }
178
179
180
_al_set_new_display_settings(ALLEGRO_EXTRA_DISPLAY_SETTINGS * settings)181 void _al_set_new_display_settings(ALLEGRO_EXTRA_DISPLAY_SETTINGS *settings)
182 {
183 thread_local_state *tls;
184 if ((tls = tls_get()) == NULL)
185 return;
186 memmove(&tls->new_display_settings, settings, sizeof(ALLEGRO_EXTRA_DISPLAY_SETTINGS));
187 }
188
189
190
_al_get_new_display_settings(void)191 ALLEGRO_EXTRA_DISPLAY_SETTINGS *_al_get_new_display_settings(void)
192 {
193 thread_local_state *tls;
194
195 if ((tls = tls_get()) == NULL)
196 return 0;
197 return &tls->new_display_settings;
198 }
199
200
201 /* Function: al_set_new_window_title
202 */
al_set_new_window_title(const char * title)203 void al_set_new_window_title(const char *title)
204 {
205 thread_local_state *tls;
206 size_t size;
207
208 if ((tls = tls_get()) == NULL)
209 return;
210
211 size = strlen(title);
212
213 if (size > ALLEGRO_NEW_WINDOW_TITLE_MAX_SIZE) {
214 size = ALLEGRO_NEW_WINDOW_TITLE_MAX_SIZE;
215 }
216
217 _al_sane_strncpy(tls->new_window_title, title, size + 1);
218 }
219
220
221
222 /* Function: al_get_new_window_title
223 */
al_get_new_window_title(void)224 const char *al_get_new_window_title(void)
225 {
226 thread_local_state *tls;
227
228 /* Return app name in case of error or if not set before. */
229 if ((tls = tls_get()) == NULL)
230 return al_get_app_name();
231
232 if (strlen(tls->new_window_title) < 1)
233 return al_get_app_name();
234
235
236 return (const char *)tls->new_window_title;
237 }
238
239
240
241
242 /* Function: al_set_new_display_flags
243 */
al_set_new_display_flags(int flags)244 void al_set_new_display_flags(int flags)
245 {
246 thread_local_state *tls;
247
248 if ((tls = tls_get()) == NULL)
249 return;
250 tls->new_display_flags = flags;
251 }
252
253
254
255 /* Function: al_get_new_display_flags
256 */
al_get_new_display_flags(void)257 int al_get_new_display_flags(void)
258 {
259 thread_local_state *tls;
260
261 if ((tls = tls_get()) == NULL)
262 return 0;
263 return tls->new_display_flags;
264 }
265
266
267
268 /* Function: al_set_new_display_refresh_rate
269 */
al_set_new_display_refresh_rate(int refresh_rate)270 void al_set_new_display_refresh_rate(int refresh_rate)
271 {
272 thread_local_state *tls;
273
274 if ((tls = tls_get()) == NULL)
275 return;
276 tls->new_display_refresh_rate = refresh_rate;
277 }
278
279
280
281 /* Function: al_get_new_display_refresh_rate
282 */
al_get_new_display_refresh_rate(void)283 int al_get_new_display_refresh_rate(void)
284 {
285 thread_local_state *tls;
286
287 if ((tls = tls_get()) == NULL)
288 return 0;
289 return tls->new_display_refresh_rate;
290 }
291
292
293
294 /* Function: al_set_new_display_adapter
295 */
al_set_new_display_adapter(int adapter)296 void al_set_new_display_adapter(int adapter)
297 {
298 thread_local_state *tls;
299
300 if ((tls = tls_get()) == NULL)
301 return;
302
303 if (adapter < 0) {
304 tls->new_display_adapter = ALLEGRO_DEFAULT_DISPLAY_ADAPTER;
305 }
306 tls->new_display_adapter = adapter;
307 }
308
309
310
311 /* Function: al_get_new_display_adapter
312 */
al_get_new_display_adapter(void)313 int al_get_new_display_adapter(void)
314 {
315 thread_local_state *tls;
316
317 if ((tls = tls_get()) == NULL)
318 return ALLEGRO_DEFAULT_DISPLAY_ADAPTER;
319 return tls->new_display_adapter;
320 }
321
322
323
324 /* Function: al_set_new_window_position
325 */
al_set_new_window_position(int x,int y)326 void al_set_new_window_position(int x, int y)
327 {
328 thread_local_state *tls;
329
330 if ((tls = tls_get()) == NULL)
331 return;
332 tls->new_window_x = x;
333 tls->new_window_y = y;
334 }
335
336
337 /* Function: al_get_new_window_position
338 */
al_get_new_window_position(int * x,int * y)339 void al_get_new_window_position(int *x, int *y)
340 {
341 thread_local_state *tls;
342 int new_window_x = INT_MAX;
343 int new_window_y = INT_MAX;
344
345 if ((tls = tls_get()) != NULL) {
346 new_window_x = tls->new_window_x;
347 new_window_y = tls->new_window_y;
348 }
349
350 if (x)
351 *x = new_window_x;
352 if (y)
353 *y = new_window_y;
354 }
355
356
357
358 /* Make the given display current, without changing the target bitmap.
359 * This is used internally to change the current display transiently.
360 */
_al_set_current_display_only(ALLEGRO_DISPLAY * display)361 bool _al_set_current_display_only(ALLEGRO_DISPLAY *display)
362 {
363 thread_local_state *tls;
364
365 if ((tls = tls_get()) == NULL)
366 return false;
367
368 if (tls->current_display &&
369 tls->current_display->vt &&
370 tls->current_display->vt->unset_current_display) {
371 tls->current_display->vt->unset_current_display(tls->current_display);
372 tls->current_display = NULL;
373 }
374
375 if (display &&
376 display->vt &&
377 display->vt->set_current_display) {
378 if (!display->vt->set_current_display(display))
379 return false;
380 }
381
382 tls->current_display = display;
383 return true;
384 }
385
386
387
388 /* Function: al_get_current_display
389 */
al_get_current_display(void)390 ALLEGRO_DISPLAY *al_get_current_display(void)
391 {
392 thread_local_state *tls;
393
394 if ((tls = tls_get()) == NULL)
395 return NULL;
396 return tls->current_display;
397 }
398
399
400
401 /* Function: al_set_target_bitmap
402 */
al_set_target_bitmap(ALLEGRO_BITMAP * bitmap)403 void al_set_target_bitmap(ALLEGRO_BITMAP *bitmap)
404 {
405 thread_local_state *tls;
406 ALLEGRO_DISPLAY *old_display;
407 ALLEGRO_DISPLAY *new_display;
408 ALLEGRO_SHADER *old_shader;
409 ALLEGRO_SHADER *new_shader;
410 bool same_shader;
411 int bitmap_flags = bitmap ? al_get_bitmap_flags(bitmap) : 0;
412
413 ASSERT(!al_is_bitmap_drawing_held());
414
415 if (bitmap) {
416 if (bitmap->parent) {
417 bitmap->parent->dirty = true;
418 }
419 else {
420 bitmap->dirty = true;
421 }
422 }
423
424 if ((tls = tls_get()) == NULL)
425 return;
426
427 old_display = tls->current_display;
428
429 if (tls->target_bitmap)
430 old_shader = tls->target_bitmap->shader;
431 else
432 old_shader = NULL;
433
434 if (bitmap == NULL) {
435 /* Explicitly releasing the current rendering context. */
436 new_display = NULL;
437 new_shader = NULL;
438 }
439 else if (bitmap_flags & ALLEGRO_MEMORY_BITMAP) {
440 /* Setting a memory bitmap doesn't change the rendering context. */
441 new_display = old_display;
442 new_shader = NULL;
443 }
444 else {
445 new_display = _al_get_bitmap_display(bitmap);
446 new_shader = bitmap->shader;
447 }
448
449 same_shader = (old_shader == new_shader && old_display == new_display);
450
451 /* Unset the old shader if necessary. */
452 if (old_shader && !same_shader) {
453 old_shader->vt->unuse_shader(old_shader, old_display);
454 }
455
456 /* Change the rendering context if necessary. */
457 if (old_display != new_display) {
458 if (old_display &&
459 old_display->vt &&
460 old_display->vt->unset_current_display) {
461 old_display->vt->unset_current_display(old_display);
462 }
463
464 tls->current_display = new_display;
465
466 if (new_display &&
467 new_display->vt &&
468 new_display->vt->set_current_display) {
469 new_display->vt->set_current_display(new_display);
470 }
471 }
472
473 /* Change the target bitmap itself. */
474 tls->target_bitmap = bitmap;
475
476 if (bitmap &&
477 !(bitmap_flags & ALLEGRO_MEMORY_BITMAP) &&
478 new_display &&
479 new_display->vt &&
480 new_display->vt->set_target_bitmap)
481 {
482 new_display->vt->set_target_bitmap(new_display, bitmap);
483
484 /* Set the new shader if necessary. This should done before the
485 * update_transformation call, which will also update the shader's
486 * al_projview_matrix variable.
487 */
488 if (!same_shader || !new_shader) {
489 al_use_shader(new_shader);
490 }
491
492 new_display->vt->update_transformation(new_display, bitmap);
493 }
494 }
495
496
497
498 /* Function: al_set_target_backbuffer
499 */
al_set_target_backbuffer(ALLEGRO_DISPLAY * display)500 void al_set_target_backbuffer(ALLEGRO_DISPLAY *display)
501 {
502 al_set_target_bitmap(al_get_backbuffer(display));
503 }
504
505
506
507 /* Function: al_get_target_bitmap
508 */
al_get_target_bitmap(void)509 ALLEGRO_BITMAP *al_get_target_bitmap(void)
510 {
511 thread_local_state *tls;
512
513 if ((tls = tls_get()) == NULL)
514 return 0;
515 return tls->target_bitmap;
516 }
517
518
519
520 /* Function: al_set_blender
521 */
al_set_blender(int op,int src,int dst)522 void al_set_blender(int op, int src, int dst)
523 {
524 al_set_separate_blender(op, src, dst, op, src, dst);
525 }
526
527
528
529 /* Function: al_set_blend_color
530 */
al_set_blend_color(ALLEGRO_COLOR color)531 void al_set_blend_color(ALLEGRO_COLOR color)
532 {
533 thread_local_state *tls;
534
535 if ((tls = tls_get()) == NULL)
536 return;
537
538 tls->current_blender.blend_color = color;
539 }
540
541
542 /* Function: al_set_separate_blender
543 */
al_set_separate_blender(int op,int src,int dst,int alpha_op,int alpha_src,int alpha_dst)544 void al_set_separate_blender(int op, int src, int dst,
545 int alpha_op, int alpha_src, int alpha_dst)
546 {
547 thread_local_state *tls;
548 ALLEGRO_BLENDER *b;
549
550 ASSERT(op >= 0 && op < ALLEGRO_NUM_BLEND_OPERATIONS);
551 ASSERT(src >= 0 && src < ALLEGRO_NUM_BLEND_MODES);
552 ASSERT(dst >= 0 && src < ALLEGRO_NUM_BLEND_MODES);
553 ASSERT(alpha_op >= 0 && alpha_op < ALLEGRO_NUM_BLEND_OPERATIONS);
554 ASSERT(alpha_src >= 0 && alpha_src < ALLEGRO_NUM_BLEND_MODES);
555 ASSERT(alpha_dst >= 0 && alpha_dst < ALLEGRO_NUM_BLEND_MODES);
556
557 if ((tls = tls_get()) == NULL)
558 return;
559
560 b = &tls->current_blender;
561
562 b->blend_op = op;
563 b->blend_source = src;
564 b->blend_dest = dst;
565 b->blend_alpha_op = alpha_op;
566 b->blend_alpha_source = alpha_src;
567 b->blend_alpha_dest = alpha_dst;
568 }
569
570
571
572 /* Function: al_get_blender
573 */
al_get_blender(int * op,int * src,int * dst)574 void al_get_blender(int *op, int *src, int *dst)
575 {
576 al_get_separate_blender(op, src, dst, NULL, NULL, NULL);
577 }
578
579
580
581 /* Function: al_get_blend_color
582 */
al_get_blend_color(void)583 ALLEGRO_COLOR al_get_blend_color(void)
584 {
585 thread_local_state *tls;
586
587 if ((tls = tls_get()) == NULL)
588 return al_map_rgba(255, 255, 255, 255);
589
590 return tls->current_blender.blend_color;
591 }
592
593
594 /* Function: al_get_separate_blender
595 */
al_get_separate_blender(int * op,int * src,int * dst,int * alpha_op,int * alpha_src,int * alpha_dst)596 void al_get_separate_blender(int *op, int *src, int *dst,
597 int *alpha_op, int *alpha_src, int *alpha_dst)
598 {
599 thread_local_state *tls;
600 ALLEGRO_BLENDER *b;
601
602 if ((tls = tls_get()) == NULL)
603 return;
604
605 b = &tls->current_blender;
606
607 if (op)
608 *op = b->blend_op;
609
610 if (src)
611 *src = b->blend_source;
612
613 if (dst)
614 *dst = b->blend_dest;
615
616 if (alpha_op)
617 *alpha_op = b->blend_alpha_op;
618
619 if (alpha_src)
620 *alpha_src = b->blend_alpha_source;
621
622 if (alpha_dst)
623 *alpha_dst = b->blend_alpha_dest;
624 }
625
626
627
628 /* Function: al_set_new_bitmap_format
629 */
al_set_new_bitmap_format(int format)630 void al_set_new_bitmap_format(int format)
631 {
632 thread_local_state *tls;
633
634 if ((tls = tls_get()) == NULL)
635 return;
636 tls->new_bitmap_format = format;
637 }
638
639
640
641 /* Function: al_set_new_bitmap_flags
642 */
al_set_new_bitmap_flags(int flags)643 void al_set_new_bitmap_flags(int flags)
644 {
645 thread_local_state *tls;
646
647 if ((tls = tls_get()) == NULL)
648 return;
649
650 tls->new_bitmap_flags = flags;
651 }
652
653
654
655 /* Function: al_add_new_bitmap_flag
656 */
al_add_new_bitmap_flag(int flag)657 void al_add_new_bitmap_flag(int flag)
658 {
659 thread_local_state *tls;
660
661 if ((tls = tls_get()) == NULL)
662 return;
663 tls->new_bitmap_flags |= flag;
664 }
665
666
667
668 /* Function: al_get_new_bitmap_format
669 */
al_get_new_bitmap_format(void)670 int al_get_new_bitmap_format(void)
671 {
672 thread_local_state *tls;
673
674 if ((tls = tls_get()) == NULL)
675 return 0;
676 return tls->new_bitmap_format;
677 }
678
679
680
681 /* Function: al_get_new_bitmap_flags
682 */
al_get_new_bitmap_flags(void)683 int al_get_new_bitmap_flags(void)
684 {
685 thread_local_state *tls;
686
687 if ((tls = tls_get()) == NULL)
688 return 0;
689 return tls->new_bitmap_flags;
690 }
691
692
693
694 /* Function: al_store_state
695 */
al_store_state(ALLEGRO_STATE * state,int flags)696 void al_store_state(ALLEGRO_STATE *state, int flags)
697 {
698 thread_local_state *tls;
699 INTERNAL_STATE *stored;
700
701 if ((tls = tls_get()) == NULL)
702 return;
703
704 stored = (void *)state;
705 stored->flags = flags;
706
707 #define _STORE(x) (stored->tls.x = tls->x)
708
709 if (flags & ALLEGRO_STATE_NEW_DISPLAY_PARAMETERS) {
710 _STORE(new_display_flags);
711 _STORE(new_display_refresh_rate);
712 _STORE(new_display_adapter);
713 _STORE(new_window_x);
714 _STORE(new_window_y);
715 _STORE(new_display_settings);
716 _al_sane_strncpy(stored->tls.new_window_title, tls->new_window_title,
717 strlen(tls->new_window_title));
718 }
719
720 if (flags & ALLEGRO_STATE_NEW_BITMAP_PARAMETERS) {
721 _STORE(new_bitmap_format);
722 _STORE(new_bitmap_flags);
723 }
724
725 if (flags & ALLEGRO_STATE_DISPLAY) {
726 _STORE(current_display);
727 }
728
729 if (flags & ALLEGRO_STATE_TARGET_BITMAP) {
730 _STORE(target_bitmap);
731 }
732
733 if (flags & ALLEGRO_STATE_BLENDER) {
734 stored->stored_blender = tls->current_blender;
735 }
736
737 if (flags & ALLEGRO_STATE_NEW_FILE_INTERFACE) {
738 _STORE(new_file_interface);
739 _STORE(fs_interface);
740 }
741
742 if (flags & ALLEGRO_STATE_TRANSFORM) {
743 ALLEGRO_BITMAP *target = al_get_target_bitmap();
744 if (!target)
745 al_identity_transform(&stored->stored_transform);
746 else
747 stored->stored_transform = target->transform;
748 }
749
750 if (flags & ALLEGRO_STATE_PROJECTION_TRANSFORM) {
751 ALLEGRO_BITMAP *target = al_get_target_bitmap();
752 if (target) {
753 stored->stored_projection_transform = target->proj_transform;
754 }
755 }
756
757 #undef _STORE
758 }
759
760
761
762 /* Function: al_restore_state
763 */
al_restore_state(ALLEGRO_STATE const * state)764 void al_restore_state(ALLEGRO_STATE const *state)
765 {
766 thread_local_state *tls;
767 INTERNAL_STATE *stored;
768 int flags;
769
770 if ((tls = tls_get()) == NULL)
771 return;
772
773 stored = (void *)state;
774 flags = stored->flags;
775
776 #define _RESTORE(x) (tls->x = stored->tls.x)
777
778 if (flags & ALLEGRO_STATE_NEW_DISPLAY_PARAMETERS) {
779 _RESTORE(new_display_flags);
780 _RESTORE(new_display_refresh_rate);
781 _RESTORE(new_display_adapter);
782 _RESTORE(new_window_x);
783 _RESTORE(new_window_y);
784 _RESTORE(new_display_settings);
785 _al_sane_strncpy(tls->new_window_title, stored->tls.new_window_title,
786 strlen(tls->new_window_title));
787 }
788
789 if (flags & ALLEGRO_STATE_NEW_BITMAP_PARAMETERS) {
790 _RESTORE(new_bitmap_format);
791 _RESTORE(new_bitmap_flags);
792 }
793
794 if (flags & ALLEGRO_STATE_DISPLAY) {
795 if (tls->current_display != stored->tls.current_display) {
796 _al_set_current_display_only(stored->tls.current_display);
797 ASSERT(tls->current_display == stored->tls.current_display);
798 }
799 }
800
801 if (flags & ALLEGRO_STATE_TARGET_BITMAP) {
802 if (tls->target_bitmap != stored->tls.target_bitmap) {
803 al_set_target_bitmap(stored->tls.target_bitmap);
804 ASSERT(tls->target_bitmap == stored->tls.target_bitmap);
805 }
806 }
807
808 if (flags & ALLEGRO_STATE_BLENDER) {
809 tls->current_blender = stored->stored_blender;
810 }
811
812 if (flags & ALLEGRO_STATE_NEW_FILE_INTERFACE) {
813 _RESTORE(new_file_interface);
814 _RESTORE(fs_interface);
815 }
816
817 if (flags & ALLEGRO_STATE_TRANSFORM) {
818 ALLEGRO_BITMAP *bitmap = al_get_target_bitmap();
819 if (bitmap)
820 al_use_transform(&stored->stored_transform);
821 }
822
823 if (flags & ALLEGRO_STATE_PROJECTION_TRANSFORM) {
824 ALLEGRO_BITMAP *bitmap = al_get_target_bitmap();
825 if (bitmap)
826 al_use_projection_transform(&stored->stored_projection_transform);
827 }
828
829 #undef _RESTORE
830 }
831
832
833
834 /* Function: al_get_new_file_interface
835 * FIXME: added a work-around for the situation where TLS has not yet been
836 * initialised when this function is called. This may happen if Allegro
837 * tries to load a configuration file before the system has been
838 * initialised. Should probably rethink the logic here...
839 */
al_get_new_file_interface(void)840 const ALLEGRO_FILE_INTERFACE *al_get_new_file_interface(void)
841 {
842 thread_local_state *tls;
843
844 if ((tls = tls_get()) == NULL)
845 return &_al_file_interface_stdio;
846
847 /* FIXME: this situation should never arise because tls_ has the stdio
848 * interface set as a default, but it arises on OS X if
849 * pthread_getspecific() is called before pthreads_thread_init()...
850 */
851 if (tls->new_file_interface)
852 return tls->new_file_interface;
853 else
854 return &_al_file_interface_stdio;
855 }
856
857
858
859 /* Function: al_set_new_file_interface
860 */
al_set_new_file_interface(const ALLEGRO_FILE_INTERFACE * file_interface)861 void al_set_new_file_interface(const ALLEGRO_FILE_INTERFACE *file_interface)
862 {
863 thread_local_state *tls;
864
865 if ((tls = tls_get()) == NULL)
866 return;
867 tls->new_file_interface = file_interface;
868 }
869
870
871
872 /* Function: al_get_fs_interface
873 */
al_get_fs_interface(void)874 const ALLEGRO_FS_INTERFACE *al_get_fs_interface(void)
875 {
876 thread_local_state *tls;
877
878 if ((tls = tls_get()) == NULL)
879 return &_al_fs_interface_stdio;
880
881 if (tls->fs_interface)
882 return tls->fs_interface;
883 else
884 return &_al_fs_interface_stdio;
885 }
886
887
888
889 /* Function: al_set_fs_interface
890 */
al_set_fs_interface(const ALLEGRO_FS_INTERFACE * fs_interface)891 void al_set_fs_interface(const ALLEGRO_FS_INTERFACE *fs_interface)
892 {
893 thread_local_state *tls;
894
895 if ((tls = tls_get()) == NULL)
896 return;
897 tls->fs_interface = fs_interface;
898 }
899
900
901
902 /* Function: al_set_standard_fs_interface
903 */
al_set_standard_fs_interface(void)904 void al_set_standard_fs_interface(void)
905 {
906 al_set_fs_interface(&_al_fs_interface_stdio);
907 }
908
909
910 #define SETTER(name, value) \
911 { \
912 thread_local_state *tls; \
913 if ((tls = tls_get()) == NULL) \
914 return; \
915 tls->name = value; \
916 }
917
918 #define GETTER(name, value) \
919 { \
920 thread_local_state *tls; \
921 if ((tls = tls_get()) == NULL) \
922 return value; \
923 return tls->name; \
924 }
925
926 /* Function: al_get_errno
927 */
al_get_errno(void)928 int al_get_errno(void)
929 GETTER(allegro_errno, 0)
930
931 /* Function: al_set_errno
932 */
933 void al_set_errno(int errnum)
934 SETTER(allegro_errno, errnum)
935
936 /* Function: al_get_new_bitmap_depth
937 */
938 int al_get_new_bitmap_depth(void)
939 GETTER(new_bitmap_depth, 0)
940
941 /* Function: al_set_new_bitmap_depth
942 */
943 void al_set_new_bitmap_depth(int depth)
944 SETTER(new_bitmap_depth, depth)
945
946 /* Function: al_get_new_bitmap_samples
947 */
948 int al_get_new_bitmap_samples(void)
949 GETTER(new_bitmap_samples, 0)
950
951 /* Function: al_set_new_bitmap_samples
952 */
953 void al_set_new_bitmap_samples(int samples)
954 SETTER(new_bitmap_samples, samples)
955
956
957
958 #ifdef ALLEGRO_ANDROID
959 JNIEnv *_al_android_get_jnienv(void)
960 GETTER(jnienv, 0)
961
962 void _al_android_set_jnienv(JNIEnv *jnienv)
963 SETTER(jnienv, jnienv)
964 #endif
965
966
967 int *_al_tls_get_dtor_owner_count(void)
968 {
969 thread_local_state *tls;
970
971 tls = tls_get();
972 return &tls->dtor_owner_count;
973 }
974
975
976 /* vim: set sts=3 sw=3 et: */
977