static void wgl_destroy_display(ALLEGRO_DISPLAY *disp) { ALLEGRO_SYSTEM_WIN *system = (ALLEGRO_SYSTEM_WIN *)al_get_system_driver(); ALLEGRO_DISPLAY_WGL *wgl_disp = (ALLEGRO_DISPLAY_WGL *)disp; ALLEGRO_DISPLAY *old_disp = al_get_current_display(); if (old_disp != disp) _al_set_current_display_only(disp); if (system->mouse_grab_display == disp) system->mouse_grab_display = NULL; destroy_display_internals(wgl_disp); _al_event_source_free(&disp->es); _al_vector_find_and_delete(&system->system.displays, &disp); _al_vector_free(&disp->bitmaps); al_free(disp->ogl_extras); if (old_disp != disp) _al_set_current_display_only(old_disp); al_free(disp->vertex_cache); al_free(wgl_disp); }
/* Function: al_destroy_display */ void al_destroy_display(ALLEGRO_DISPLAY *display) { if (display) { /* This causes warnings and potential errors on Android because * it clears the context and Android needs this thread to have * the context bound in its destroy function and to destroy the * shader. Just skip this part on Android. */ #ifndef ALLEGRO_ANDROID ALLEGRO_BITMAP *bmp; bmp = al_get_target_bitmap(); if (bmp && _al_get_bitmap_display(bmp) == display) al_set_target_bitmap(NULL); /* This can happen if we have a current display, but the target bitmap * was a memory bitmap. */ if (display == al_get_current_display()) _al_set_current_display_only(NULL); #endif al_destroy_shader(display->default_shader); display->default_shader = NULL; ASSERT(display->vt); display->vt->destroy_display(display); } }
/* Function: al_restore_state */ void al_restore_state(ALLEGRO_STATE const *state) { thread_local_state *tls; INTERNAL_STATE *stored; int flags; if ((tls = tls_get()) == NULL) return; stored = (void *)state; flags = stored->flags; if (flags & ALLEGRO_STATE_NEW_DISPLAY_PARAMETERS) { _STORE(new_display_flags); _STORE(new_display_refresh_rate); _STORE(new_display_adapter); _STORE(new_window_x); _STORE(new_window_y); _STORE(new_display_settings); } if (flags & ALLEGRO_STATE_NEW_BITMAP_PARAMETERS) { _STORE(new_bitmap_format); _STORE(new_bitmap_flags); } if (flags & ALLEGRO_STATE_DISPLAY) { _STORE(current_display); _al_set_current_display_only(tls->current_display); } if (flags & ALLEGRO_STATE_TARGET_BITMAP) { _STORE(target_bitmap); al_set_target_bitmap(tls->target_bitmap); } if (flags & ALLEGRO_STATE_BLENDER) { tls->current_blender = stored->stored_blender; } if (flags & ALLEGRO_STATE_NEW_FILE_INTERFACE) { _STORE(new_file_interface); _STORE(fs_interface); } if (flags & ALLEGRO_STATE_TRANSFORM) { ALLEGRO_BITMAP *bitmap = al_get_target_bitmap(); if (bitmap) al_use_transform(&stored->stored_transform); } }
/* Function: al_set_current_opengl_context */ void al_set_current_opengl_context(ALLEGRO_DISPLAY *display) { ASSERT(display); if (!(display->flags & ALLEGRO_OPENGL)) return; if (display) { ALLEGRO_BITMAP *bmp = al_get_target_bitmap(); if (bmp && bmp->display && bmp->display != display) { al_set_target_bitmap(NULL); } } _al_set_current_display_only(display); }
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; } }
ALLEGRO_LOCKED_REGION *_al_ogl_lock_region_new(ALLEGRO_BITMAP *bitmap, int x, int y, int w, int h, int format, int flags) { ALLEGRO_BITMAP_EXTRA_OPENGL * const ogl_bitmap = bitmap->extra; const GLint gl_y = bitmap->h - y - h; ALLEGRO_DISPLAY *disp; ALLEGRO_DISPLAY *old_disp = NULL; ALLEGRO_BITMAP *old_target = al_get_target_bitmap(); GLenum e; bool ok; bool restore_fbo = false; if (format == ALLEGRO_PIXEL_FORMAT_ANY) { /* Never pick compressed formats with ANY, as it interacts weirdly with * existing code (e.g. al_get_pixel_size() etc) */ int bitmap_format = al_get_bitmap_format(bitmap); if (_al_pixel_format_is_compressed(bitmap_format)) { // XXX Get a good format from the driver? format = ALLEGRO_PIXEL_FORMAT_ABGR_8888_LE; } else { format = bitmap_format; } } disp = al_get_current_display(); format = _al_get_real_pixel_format(disp, format); /* Change OpenGL context if necessary. */ if (!disp || (_al_get_bitmap_display(bitmap)->ogl_extras->is_shared == false && _al_get_bitmap_display(bitmap) != disp)) { old_disp = disp; _al_set_current_display_only(_al_get_bitmap_display(bitmap)); } ok = true; /* Set up the pixel store state. We will need to match it when unlocking. * There may be other pixel store state we should be setting. * See also pitfalls 7 & 8 from: * http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/ */ glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); { const int pixel_size = al_get_pixel_size(format); const int pixel_alignment = ogl_pixel_alignment(pixel_size); glPixelStorei(GL_PACK_ALIGNMENT, pixel_alignment); e = glGetError(); if (e) { ALLEGRO_ERROR("glPixelStorei(GL_PACK_ALIGNMENT, %d) failed (%s).\n", pixel_alignment, _al_gl_error_string(e)); ok = false; } } if (ok) { if (ogl_bitmap->is_backbuffer) { ALLEGRO_DEBUG("Locking backbuffer\n"); ok = ogl_lock_region_backbuffer(bitmap, ogl_bitmap, x, gl_y, w, h, format, flags); } else if (flags & ALLEGRO_LOCK_WRITEONLY) { ALLEGRO_DEBUG("Locking non-backbuffer WRITEONLY\n"); ok = ogl_lock_region_nonbb_writeonly(bitmap, ogl_bitmap, x, gl_y, w, h, format); } else { ALLEGRO_DEBUG("Locking non-backbuffer READWRITE\n"); ok = ogl_lock_region_nonbb_readwrite(bitmap, ogl_bitmap, x, gl_y, w, h, format, &restore_fbo); } } glPopClientAttrib(); /* Restore state after switching FBO. */ if (restore_fbo) { if (!old_target) { /* Old target was NULL; release the context. */ _al_set_current_display_only(NULL); } else if (!_al_get_bitmap_display(old_target)) { /* Old target was memory bitmap; leave the current display alone. */ } else if (old_target != bitmap) { /* Old target was another OpenGL bitmap. */ _al_ogl_setup_fbo(_al_get_bitmap_display(old_target), old_target); } } ASSERT(al_get_target_bitmap() == old_target); if (old_disp != NULL) { _al_set_current_display_only(old_disp); } if (ok) { return &bitmap->locked_region; } ALLEGRO_ERROR("Failed to lock region\n"); ASSERT(ogl_bitmap->lock_buffer == NULL); return NULL; }
static void ogl_unlock_region_non_readonly(ALLEGRO_BITMAP *bitmap, ALLEGRO_BITMAP_EXTRA_OPENGL *ogl_bitmap) { const int lock_format = bitmap->locked_region.format; const int gl_y = bitmap->h - bitmap->lock_y - bitmap->lock_h; ALLEGRO_DISPLAY *old_disp = NULL; ALLEGRO_DISPLAY *disp; int orig_format; bool biased_alpha = false; GLenum e; disp = al_get_current_display(); orig_format = _al_get_real_pixel_format(disp, _al_get_bitmap_memory_format(bitmap)); /* Change OpenGL context if necessary. */ if (!disp || (_al_get_bitmap_display(bitmap)->ogl_extras->is_shared == false && _al_get_bitmap_display(bitmap) != disp)) { old_disp = disp; _al_set_current_display_only(_al_get_bitmap_display(bitmap)); } /* Keep this in sync with ogl_lock_region. */ glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); { const int lock_pixel_size = al_get_pixel_size(lock_format); const int pixel_alignment = ogl_pixel_alignment(lock_pixel_size); glPixelStorei(GL_UNPACK_ALIGNMENT, pixel_alignment); e = glGetError(); if (e) { ALLEGRO_ERROR("glPixelStorei(GL_UNPACK_ALIGNMENT, %d) failed (%s).\n", pixel_alignment, _al_gl_error_string(e)); } } if (exactly_15bpp(lock_format)) { /* OpenGL does not support 15-bpp internal format without an alpha, * so when storing such data we must ensure the alpha bit is set. */ glPixelTransferi(GL_ALPHA_BIAS, 1); biased_alpha = true; } if (ogl_bitmap->is_backbuffer) { ALLEGRO_DEBUG("Unlocking backbuffer\n"); ogl_unlock_region_backbuffer(bitmap, ogl_bitmap, gl_y); } else { glBindTexture(GL_TEXTURE_2D, ogl_bitmap->texture); if (ogl_bitmap->fbo_info) { ALLEGRO_DEBUG("Unlocking non-backbuffer (FBO)\n"); ogl_unlock_region_nonbb_fbo(bitmap, ogl_bitmap, gl_y, orig_format); } else { ALLEGRO_DEBUG("Unlocking non-backbuffer (non-FBO)\n"); ogl_unlock_region_nonbb_nonfbo(bitmap, ogl_bitmap, gl_y); } /* If using FBOs, we need to regenerate mipmaps explicitly now. */ /* XXX why don't we check ogl_bitmap->fbo_info? */ if ((al_get_bitmap_flags(bitmap) & ALLEGRO_MIPMAP) && al_get_opengl_extension_list()->ALLEGRO_GL_EXT_framebuffer_object) { glGenerateMipmapEXT(GL_TEXTURE_2D); e = glGetError(); if (e) { ALLEGRO_ERROR("glGenerateMipmapEXT for texture %d failed (%s).\n", ogl_bitmap->texture, _al_gl_error_string(e)); } } } if (biased_alpha) { glPixelTransferi(GL_ALPHA_BIAS, 0); } glPopClientAttrib(); if (old_disp) { _al_set_current_display_only(old_disp); } }
ALLEGRO_LOCKED_REGION *_al_ogl_lock_region_new(ALLEGRO_BITMAP *bitmap, int x, int y, int w, int h, int format, int flags) { ALLEGRO_BITMAP_EXTRA_OPENGL * const ogl_bitmap = bitmap->extra; const GLint gl_y = bitmap->h - y - h; ALLEGRO_DISPLAY *disp; ALLEGRO_DISPLAY *old_disp = NULL; GLenum e; if (format == ALLEGRO_PIXEL_FORMAT_ANY) { format = bitmap->format; } disp = al_get_current_display(); format = _al_get_real_pixel_format(disp, format); /* Change OpenGL context if necessary. */ if (!disp || (bitmap->display->ogl_extras->is_shared == false && bitmap->display != disp)) { old_disp = disp; _al_set_current_display_only(bitmap->display); } /* Set up the pixel store state. We will need to match it when unlocking. * There may be other pixel store state we should be setting. * See also pitfalls 7 & 8 from: * http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/ */ glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); { const int pixel_size = al_get_pixel_size(format); const int pixel_alignment = ogl_pixel_alignment(pixel_size); glPixelStorei(GL_PACK_ALIGNMENT, pixel_alignment); e = glGetError(); if (e) { ALLEGRO_ERROR("glPixelStorei(GL_PACK_ALIGNMENT, %d) failed (%s).\n", pixel_alignment, _al_gl_error_string(e)); } } if (ogl_bitmap->is_backbuffer) { ALLEGRO_DEBUG("Locking backbuffer\n"); ogl_lock_region_backbuffer(bitmap, ogl_bitmap, x, gl_y, w, h, format, flags); } else if (flags & ALLEGRO_LOCK_WRITEONLY) { ALLEGRO_DEBUG("Locking non-backbuffer WRITEONLY\n"); ogl_lock_region_nonbb_writeonly(bitmap, ogl_bitmap, x, gl_y, w, h, format); } else { ALLEGRO_DEBUG("Locking non-backbuffer READWRITE\n"); ogl_lock_region_nonbb_readwrite(bitmap, ogl_bitmap, x, gl_y, w, h, format); } glPopClientAttrib(); if (old_disp != NULL) { _al_set_current_display_only(old_disp); } return &bitmap->locked_region; }
/* Function: al_create_display */ ALLEGRO_DISPLAY *al_create_display(int w, int h) { ALLEGRO_SYSTEM *system; ALLEGRO_DISPLAY_INTERFACE *driver; ALLEGRO_DISPLAY *display; ALLEGRO_EXTRA_DISPLAY_SETTINGS *settings; int flags; system = al_get_system_driver(); driver = system->vt->get_display_driver(); if (!driver) { ALLEGRO_ERROR("Failed to create display (no display driver)\n"); return NULL; } display = driver->create_display(w, h); if (!display) { ALLEGRO_ERROR("Failed to create display (NULL)\n"); return NULL; } ASSERT(display->vt); settings = &display->extra_settings; flags = settings->required | settings->suggested; if (!(flags & (1 << ALLEGRO_AUTO_CONVERT_BITMAPS))) { settings->settings[ALLEGRO_AUTO_CONVERT_BITMAPS] = 1; } display->min_w = 0; display->min_h = 0; display->max_w = 0; display->max_h = 0; display->use_constraints = false; display->vertex_cache = 0; display->num_cache_vertices = 0; display->cache_enabled = false; display->vertex_cache_size = 0; display->cache_texture = 0; al_identity_transform(&display->projview_transform); display->default_shader = NULL; _al_vector_init(&display->display_invalidated_callbacks, sizeof(void *)); _al_vector_init(&display->display_validated_callbacks, sizeof(void *)); display->render_state.write_mask = ALLEGRO_MASK_RGBA | ALLEGRO_MASK_DEPTH; display->render_state.depth_test = false; display->render_state.depth_function = ALLEGRO_RENDER_LESS; display->render_state.alpha_test = false; display->render_state.alpha_function = ALLEGRO_RENDER_ALWAYS; display->render_state.alpha_test_value = 0; _al_vector_init(&display->bitmaps, sizeof(ALLEGRO_BITMAP*)); if (settings->settings[ALLEGRO_COMPATIBLE_DISPLAY]) { al_set_target_bitmap(al_get_backbuffer(display)); } else { ALLEGRO_DEBUG("ALLEGRO_COMPATIBLE_DISPLAY not set\n"); _al_set_current_display_only(display); } if (display->flags & ALLEGRO_PROGRAMMABLE_PIPELINE) { display->default_shader = _al_create_default_shader(display->flags); if (!display->default_shader) { al_destroy_display(display); return NULL; } al_use_shader(display->default_shader); } /* Clear the screen */ if (settings->settings[ALLEGRO_COMPATIBLE_DISPLAY]) { al_clear_to_color(al_map_rgb(0, 0, 0)); /* TODO: * on iphone, don't kill the initial splashscreen - in fact, it's also * annoying in linux to have an extra black frame as first frame and I * suppose we never really want it */ #if 0 al_flip_display(); #endif } if (settings->settings[ALLEGRO_AUTO_CONVERT_BITMAPS]) { /* We convert video bitmaps to memory bitmaps when the display is * destroyed, so seems only fair to re-convertt hem when the * display is re-created again. */ al_convert_memory_bitmaps(); } return display; }