indexing description: "[ A texture which takes the content from an EM_SURFACE. The texture is updated automatically when `surface' is modified. The width and height of the texture will be the smallest power of 2 which is greater than the dimensions of `surface'. ]" date: "$Date$" revision: "$Revision$" class GL_SURFACE_TEXTURE inherit GL_TEXTURE EM_SHARED_BITMAP_FACTORY export {NONE} all end EM_SHARED_ERROR_HANDLER export {NONE} all end EM_CONSTANTS export {NONE} all end SDL_VIDEO_FUNCTIONS_EXTERNAL export {NONE} all end MEMORY export {NONE} all redefine dispose end create make_from_surface feature {NONE} -- Initialisation make_from_surface (a_surface: EM_SURFACE) is -- Initialise texture with `a_surface'. require a_surface_not_void: a_surface /= Void do gl_gen_textures_external (1, $internal_id) set_surface (a_surface) ensure surface_set: surface = a_surface texture_created: is_valid end feature -- Access id: INTEGER is -- OpenGL texture id do if surface.is_modified then generate_texture surface.set_unmodified end Result := internal_id end surface: EM_SURFACE -- Surface which is used for texture data feature -- Element change set_surface (a_surface: EM_SURFACE) is -- Set `surface' to `a_surface'. require a_surface_not_void: a_surface /= Void do surface := a_surface compute_texture_size Bitmap_factory.create_empty_open_gl_bitmap (width, height) internal_surface := Bitmap_factory.last_bitmap generate_texture surface.set_unmodified ensure surface_set: surface = a_surface end feature {NONE} -- Implementation internal_id: INTEGER -- OpenGL id of texture internal_surface: EM_SURFACE -- OpenGL surface which holds pixel data compute_texture_size is -- Compute texture size as next higher power of 2 of surface dimension. do from width := 1 until width >= surface.width loop width := width * 2 end from height := 1 until height >= surface.height loop height := height * 2 end end generate_texture is -- Generate texture for `surface'. require internal_surface_not_void: internal_surface /= Void local alpha_was_enabled: BOOLEAN saved_flags: INTEGER saved_alpha: INTEGER error: INTEGER c_string: EWG_ZERO_TERMINATED_STRING do saved_flags := surface.flags & (Em_srcalpha | Em_rleaccelok) alpha_was_enabled := surface.is_alpha_transparency_enabled if alpha_was_enabled then saved_alpha := surface.alpha_value surface.disable_alpha_transparency end -- blit to surface with correct (power of 2) dimensions internal_surface.blit_surface (surface, 0, 0) -- restore the alpha blending attributes if alpha_was_enabled then error := sdl_set_alpha_external (surface.item, saved_flags, saved_alpha) end -- Clear OpenGL errors that may have occured from until gl_get_error_external = 0 loop end gl_bind_texture_external (Em_gl_texture_2d, internal_id) gl_tex_parameteri_external (Em_gl_texture_2d, Em_gl_texture_mag_filter, Em_gl_nearest) gl_tex_parameteri_external (Em_gl_texture_2d, Em_gl_texture_min_filter, Em_gl_nearest) gl_tex_image2d_external ( Em_gl_texture_2d, 0, Em_gl_rgba, width, height, 0, Em_gl_rgba, Em_gl_unsigned_byte, internal_surface.pixels ) error := gl_get_error_external if error /= 0 then create c_string.make_shared (glu_error_string_external (error)) Error_handler.raise_warning (Error_handler.Em_error_generate_texture, [c_string.string]) end end dispose is -- Free OpenGL texture. do if internal_id > 0 and not is_not_freeing_texture then gl_delete_textures_external (1, $internal_id) internal_id := 0 end Precursor end invariant width_at_least_surface_width: width >= surface.width hieght_at_least_surface_height: height >= surface.height end