/* _al_run_destructors: * Run all the destructors on the list in reverse order. */ void _al_run_destructors(_AL_DTOR_LIST *dtors) { if (!dtors) { return; } /* call the destructors in reverse order */ _al_mutex_lock(&dtors->mutex); { while (!_al_vector_is_empty(&dtors->dtors)) { DTOR *dtor = _al_vector_ref_back(&dtors->dtors); void *object = dtor->object; void (*func)(void *) = dtor->func; ALLEGRO_DEBUG("calling dtor for %s %p, func %p\n", dtor->name, object, func); _al_mutex_unlock(&dtors->mutex); { (*func)(object); } _al_mutex_lock(&dtors->mutex); } } _al_mutex_unlock(&dtors->mutex); }
/* Destroys all bitmaps created for this display. */ void _al_destroy_display_bitmaps(ALLEGRO_DISPLAY *d) { while (_al_vector_size(&d->bitmaps) > 0) { ALLEGRO_BITMAP **bptr = _al_vector_ref_back(&d->bitmaps); ALLEGRO_BITMAP *b = *bptr; al_destroy_bitmap(b); } }
static void unlock_current_page(ALLEGRO_TTF_FONT_DATA *data) { if (data->page_lr) { ALLEGRO_BITMAP **back = _al_vector_ref_back(&data->page_bitmaps); ASSERT(al_is_bitmap_locked(*back)); al_unlock_bitmap(*back); data->page_lr = NULL; } }
static void convert_display_bitmaps_to_memory_bitmap(ALLEGRO_DISPLAY *d) { ALLEGRO_DEBUG("converting display bitmaps to memory bitmaps.\n"); while (d->bitmaps._size > 0) { ALLEGRO_BITMAP **bptr = _al_vector_ref_back(&d->bitmaps); ALLEGRO_BITMAP *b = *bptr; _al_convert_to_memory_bitmap(b); } }
/* Internal function: _al_event_source_free * Free the resources using by an event source structure. It * automatically unregisters the event source from all the event * queues it is currently registered with. */ void _al_event_source_free(ALLEGRO_EVENT_SOURCE *es) { ALLEGRO_EVENT_SOURCE_REAL *this = (ALLEGRO_EVENT_SOURCE_REAL *)es; /* Unregister from all queues. */ while (!_al_vector_is_empty(&this->queues)) { ALLEGRO_EVENT_QUEUE **slot = _al_vector_ref_back(&this->queues); al_unregister_event_source(*slot, es); } _al_vector_free(&this->queues); _al_mutex_destroy(&this->mutex); }
static void destroy_display_internals(ALLEGRO_DISPLAY_WGL *wgl_disp) { ALLEGRO_DISPLAY *disp = (ALLEGRO_DISPLAY *)wgl_disp; ALLEGRO_DISPLAY_WIN *win_disp = (ALLEGRO_DISPLAY_WIN *)wgl_disp; /* We need to convert all our bitmaps to display independent (memory) * bitmaps because WGL driver doesn't support sharing of resources. */ while (disp->bitmaps._size > 0) { ALLEGRO_BITMAP **bptr = _al_vector_ref_back(&disp->bitmaps); ALLEGRO_BITMAP *bmp = *bptr; _al_convert_to_memory_bitmap(bmp); } if (disp->ogl_extras->backbuffer) _al_ogl_destroy_backbuffer(disp->ogl_extras->backbuffer); disp->ogl_extras->backbuffer = NULL; _al_ogl_unmanage_extensions(disp); PostMessage(win_disp->window, _al_win_msg_suicide, (WPARAM)win_disp, 0); while (!win_disp->thread_ended) al_rest(0.001); if (wgl_disp->glrc) { wglDeleteContext(wgl_disp->glrc); wgl_disp->glrc = NULL; } if (wgl_disp->dc) { ReleaseDC(win_disp->window, wgl_disp->dc); wgl_disp->dc = NULL; } if (disp->flags & ALLEGRO_FULLSCREEN && !_wgl_do_not_change_display_mode) { ChangeDisplaySettings(NULL, 0); } if (win_disp->window) { DestroyWindow(win_disp->window); win_disp->window = NULL; } }
/* Function: al_destroy_menu */ void al_destroy_menu(ALLEGRO_MENU *menu) { ALLEGRO_MENU_ITEM **slot; size_t i; ASSERT(menu); if (menu->parent) { /* If the menu is attached to a menu item, then this is equivelant to removing that menu item. */ ALLEGRO_MENU *parent = menu->parent->parent; ASSERT(parent); for (i = 0; i < _al_vector_size(&parent->items); ++i) { slot = _al_vector_ref(&parent->items, i); if (*slot == menu->parent) { al_remove_menu_item(parent, 0 - (int) i); return; } } /* Should never get here. */ ASSERT(false); return; } else if (menu->display && !menu->is_popup_menu) { /* This is an active, top-level menu. */ al_remove_display_menu(menu->display); } /* Destroy each item associated with the menu. */ while (_al_vector_size(&menu->items)) { slot = _al_vector_ref_back(&menu->items); destroy_menu_item(*slot); } _al_vector_free(&menu->items); al_disable_menu_event_source(menu); al_free(menu); }
static void destroy_display_internals(ALLEGRO_DISPLAY_WGL *wgl_disp) { ALLEGRO_DISPLAY *disp = (ALLEGRO_DISPLAY *)wgl_disp; ALLEGRO_DISPLAY_WIN *win_disp = (ALLEGRO_DISPLAY_WIN *)wgl_disp; /* We need to convert all our bitmaps to display independent (memory) * bitmaps because WGL driver doesn't support sharing of resources. */ while (disp->bitmaps._size > 0) { ALLEGRO_BITMAP **bptr = _al_vector_ref_back(&disp->bitmaps); ALLEGRO_BITMAP *bmp = *bptr; _al_convert_to_memory_bitmap(bmp); } if (disp->ogl_extras->backbuffer) _al_ogl_destroy_backbuffer(disp->ogl_extras->backbuffer); disp->ogl_extras->backbuffer = NULL; _al_ogl_unmanage_extensions(disp); PostMessage(win_disp->window, _al_win_msg_suicide, (WPARAM)win_disp, 0); while (!win_disp->thread_ended) al_rest(0.001); }
/* Function: al_destroy_event_queue */ void al_destroy_event_queue(ALLEGRO_EVENT_QUEUE *queue) { ASSERT(queue); _al_unregister_destructor(_al_dtor_list, queue); /* Unregister any event sources registered with this queue. */ while (_al_vector_is_nonempty(&queue->sources)) { ALLEGRO_EVENT_SOURCE **slot = _al_vector_ref_back(&queue->sources); al_unregister_event_source(queue, *slot); } ASSERT(_al_vector_is_empty(&queue->sources)); _al_vector_free(&queue->sources); ASSERT(queue->events_head == queue->events_tail); _al_vector_free(&queue->events); _al_cond_destroy(&queue->cond); _al_mutex_destroy(&queue->mutex); al_free(queue); }
static void raspberrypi_destroy_display(ALLEGRO_DISPLAY *d) { ALLEGRO_DISPLAY_RASPBERRYPI *pidisplay = (ALLEGRO_DISPLAY_RASPBERRYPI *)d; hide_cursor(pidisplay); delete_cursor_data(pidisplay); _al_set_current_display_only(d); while (d->bitmaps._size > 0) { ALLEGRO_BITMAP **bptr = (ALLEGRO_BITMAP **)_al_vector_ref_back(&d->bitmaps); ALLEGRO_BITMAP *b = *bptr; _al_convert_to_memory_bitmap(b); } _al_event_source_free(&d->es); ALLEGRO_SYSTEM_RASPBERRYPI *system = (void *)al_get_system_driver(); _al_vector_find_and_delete(&system->system.displays, &d); eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroySurface(egl_display, egl_window); eglDestroyContext(egl_display, egl_context); eglTerminate(egl_display); if (getenv("DISPLAY")) { _al_mutex_lock(&system->lock); XUnmapWindow(system->x11display, pidisplay->window); XDestroyWindow(system->x11display, pidisplay->window); _al_mutex_unlock(&system->lock); } if (system->mouse_grab_display == d) { system->mouse_grab_display = NULL; } }
static bool wgl_resize_helper(ALLEGRO_DISPLAY *d, int width, int height) { ALLEGRO_DISPLAY_WGL *wgl_disp = (ALLEGRO_DISPLAY_WGL *)d; ALLEGRO_DISPLAY *ogl_disp = (ALLEGRO_DISPLAY *)d; ALLEGRO_DISPLAY_WIN *win_disp = (ALLEGRO_DISPLAY_WIN *)d; int full_w, full_h; ALLEGRO_MONITOR_INFO mi; int adapter = al_get_new_display_adapter(); if (adapter < 0) adapter = 0; al_get_monitor_info(adapter, &mi); full_w = mi.x2 - mi.x1; full_h = mi.y2 - mi.y1; if ((d->flags & ALLEGRO_FULLSCREEN_WINDOW) && (full_w != width || full_h != height)) { win_disp->toggle_w = width; win_disp->toggle_h = height; return true; } win_disp->can_acknowledge = false; if (d->flags & ALLEGRO_FULLSCREEN) { ALLEGRO_BITMAP *target_bmp; _AL_VECTOR disp_bmps; bool was_backbuffer = false; size_t i; target_bmp = al_get_target_bitmap(); if (target_bmp->vt) was_backbuffer = ((ALLEGRO_BITMAP_OGL*)target_bmp)->is_backbuffer; /* Remeber display bitmaps. */ _al_vector_init(&disp_bmps, sizeof(ALLEGRO_BITMAP*)); for (i = 0; i < _al_vector_size(&d->bitmaps); i++) { ALLEGRO_BITMAP **dis = _al_vector_ref(&d->bitmaps, i); ALLEGRO_BITMAP **mem = _al_vector_alloc_back(&disp_bmps); *mem = *dis; } /* This flag prevents from switching to desktop resolution in between. */ _wgl_do_not_change_display_mode = true; destroy_display_internals(wgl_disp); _wgl_do_not_change_display_mode = false; d->w = width; d->h = height; if (!create_display_internals(wgl_disp)) return false; /* Reupload bitmaps. */ while (_al_vector_is_nonempty(&disp_bmps)) { ALLEGRO_BITMAP **back = _al_vector_ref_back(&disp_bmps); _al_convert_to_display_bitmap(*back); _al_vector_delete_at(&disp_bmps, _al_vector_size(&disp_bmps) - 1); } /* We have a new backbuffer now. */ if (was_backbuffer) al_set_target_bitmap(al_get_backbuffer(d)); } else { RECT win_size; WINDOWINFO wi; win_size.left = 0; win_size.top = 0; win_size.right = width; win_size.bottom = height; wi.cbSize = sizeof(WINDOWINFO); GetWindowInfo(win_disp->window, &wi); AdjustWindowRectEx(&win_size, wi.dwStyle, false, wi.dwExStyle); if (!SetWindowPos(win_disp->window, HWND_TOP, 0, 0, win_size.right - win_size.left, win_size.bottom - win_size.top, SWP_NOMOVE|SWP_NOZORDER)) return false; PostMessage(win_disp->window, WM_USER+0, 0, 0); d->w = width; d->h = height; if (!(d->flags & ALLEGRO_FULLSCREEN_WINDOW)) { win_disp->toggle_w = width; win_disp->toggle_h = height; } _al_ogl_resize_backbuffer(ogl_disp->ogl_extras->backbuffer, width, height); setup_gl(d); } return true; }
static void xdpy_destroy_display(ALLEGRO_DISPLAY *d) { ALLEGRO_SYSTEM_XGLX *s = (void *)al_get_system_driver(); ALLEGRO_DISPLAY_XGLX *glx = (void *)d; ALLEGRO_OGL_EXTRAS *ogl = d->ogl_extras; ALLEGRO_DEBUG("destroy display.\n"); /* If we're the last display, convert all bitmpas to display independent * (memory) bitmaps. */ if (s->system.displays._size == 1) { while (d->bitmaps._size > 0) { ALLEGRO_BITMAP **bptr = _al_vector_ref_back(&d->bitmaps); ALLEGRO_BITMAP *b = *bptr; _al_convert_to_memory_bitmap(b); } } else { /* Pass all bitmaps to any other living display. (We assume all displays * are compatible.) */ size_t i; ALLEGRO_DISPLAY **living = NULL; ASSERT(s->system.displays._size > 1); for (i = 0; i < s->system.displays._size; i++) { living = _al_vector_ref(&s->system.displays, i); if (*living != d) break; } for (i = 0; i < d->bitmaps._size; i++) { ALLEGRO_BITMAP **add = _al_vector_alloc_back(&(*living)->bitmaps); ALLEGRO_BITMAP **ref = _al_vector_ref(&d->bitmaps, i); *add = *ref; (*add)->display = *living; } } _al_xglx_unuse_adapter(s, glx->adapter); _al_ogl_unmanage_extensions(d); ALLEGRO_DEBUG("unmanaged extensions.\n"); _al_mutex_lock(&s->lock); _al_vector_find_and_delete(&s->system.displays, &d); XDestroyWindow(s->x11display, glx->window); if (s->mouse_grab_display == d) { s->mouse_grab_display = NULL; } ALLEGRO_DEBUG("destroy window.\n"); if (d->flags & ALLEGRO_FULLSCREEN) { size_t i; ALLEGRO_DISPLAY **living = NULL; bool last_fullscreen = true; /* If any other fullscreen display is still active on the same adapter, * we must not touch the video mode. */ for (i = 0; i < s->system.displays._size; i++) { living = _al_vector_ref(&s->system.displays, i); ALLEGRO_DISPLAY_XGLX *living_glx = (void*)*living; if (*living == d) continue; /* check for fullscreen displays on the same adapter */ if (living_glx->adapter == glx->adapter && al_get_display_flags(*living) & ALLEGRO_FULLSCREEN) { last_fullscreen = false; } } if (last_fullscreen) { ALLEGRO_DEBUG("restore modes.\n"); _al_xglx_restore_video_mode(s, glx->adapter); } else { ALLEGRO_DEBUG("*not* restoring modes.\n"); } } if (ogl->backbuffer) { _al_ogl_destroy_backbuffer(ogl->backbuffer); ogl->backbuffer = NULL; ALLEGRO_DEBUG("destroy backbuffer.\n"); } if (glx->context) { glXDestroyContext(s->gfxdisplay, glx->context); glx->context = NULL; ALLEGRO_DEBUG("destroy context.\n"); } /* XXX quick pre-release hack */ /* In multi-window programs these result in a double-free bugs. */ #if 0 if (glx->fbc) { al_free(glx->fbc); glx->fbc = NULL; XFree(glx->xvinfo); glx->xvinfo = NULL; } else if (glx->xvinfo) { al_free(glx->xvinfo); glx->xvinfo = NULL; } #endif _al_cond_destroy(&glx->mapped); _al_vector_free(&d->bitmaps); _al_event_source_free(&d->es); al_free(d->ogl_extras); al_free(d->vertex_cache); al_free(d); _al_mutex_unlock(&s->lock); ALLEGRO_DEBUG("destroy display finished.\n"); }