indexing description: "[ Singleton representing the video subsystem. Use EM_SHARED_SUBSYSTEMS to access this class. ]" date: "$Date$" revision: "$Revision$" class EM_VIDEO_SUBSYSTEM inherit EM_SUBSYSTEM SDL_VIDEO_FUNCTIONS_EXTERNAL export {NONE} all end SDL_MOUSE_FUNCTIONS_EXTERNAL export {NONE} all end SDL_GLATTR_ENUM_EXTERNAL export {NONE} all end SDL_ERROR_FUNCTIONS_EXTERNAL export {NONE} all end GLEW_FUNCTIONS export {NONE} all end EM_CONSTANTS export {NONE} all end create {EM_SHARED_VIDEO_SUBSYSTEM} make feature {NONE} -- Initialisation make is do -- Set some sensible defaults for the openGL attributes gl_red_size := 8 gl_green_size := 8 gl_blue_size := 8 gl_alpha_size := 0 gl_accum_red_size := 0 gl_accum_green_size := 0 gl_accum_blue_size := 0 gl_accum_alpha_size := 0 gl_buffer_size := 24 gl_depth_size := 16 gl_stencil_size := 8 gl_multisample_buffers := 1 gl_multisample_samples := 4 -- Also set some meaningful default values for video surface attributes. set_video_surface_width (1024) set_video_surface_height (768) set_video_bpp (32) set_hwpalette (true) set_fullscreen (false) set_doublebuffered (true) set_hardware_surface (false) is_enabled := False ensure not_enabled: not is_enabled end feature -- Access video_surface: EM_VIDEO_SURFACE -- Video surface video_surface_width: INTEGER -- Width of the video surface video_surface_height: INTEGER -- Height of the video surface video_surface_bpp: INTEGER -- Bits per pixel of the video surface default_cursor: EM_CURSOR -- Default screen cursor feature -- Status report is_enabled: BOOLEAN -- Is video subsystem enabled? is_cursor_visible: BOOLEAN is -- Is cursor currently visible? require video_subsystem_enabled: is_enabled local i: INTEGER do i := sdl_show_cursor_external (Em_query) check valid_return: i = Em_enable or i = Em_disable end if i = Em_enable then Result := True end end feature -- Subsystem management enable is -- Create an EiffelMedia system with the video subsystem enabled and -- the time subsystem enabled. local err: INTEGER p: POINTER rect: EM_BLITTING_RECTANGLE error_string: EWG_ZERO_TERMINATED_STRING do base_enable -- Base enable alredy enables video subsystem. So all we have to do is check if the options are ok. if 0 /= sdl_video_mode_ok_external (video_surface_width, video_surface_height, video_surface_bpp, video_surface_flags) then -- If we are in openGL mode set the attributes if opengl_enabled then opengl_set_attributes end p := sdl_set_video_mode_external (video_surface_width, video_surface_height, video_surface_bpp, video_surface_flags) if p /= Default_pointer then create video_surface.make (p, opengl_enabled) -- Ensure to initialize clipping to whole screen, cause with opengl enabled, there seems to be a missinitialization. create rect.make (0, 0, video_surface_width, video_surface_height) video_surface.set_clipping_rectangle (rect) if opengl_enabled then -- Load Glew err := init if em_glew_ok /= err then error_handler.raise_error (error_handler.Em_error_opengl_init_glew, [get_error_string (err)]) end end else create error_string.make_shared( sdl_get_error_external ) Error_handler.raise_error (Error_handler.Em_error_set_video_mode, [error_string.string]) end else Error_handler.raise_error (Error_handler.Em_error_video_mode_not_supported, [video_surface_width, video_surface_height, video_surface_bpp, video_surface_flags]) end create default_cursor.make_from_pointer (sdl_get_cursor_external, False) is_enabled := True end disable is do is_enabled := False video_surface := Void base_disable end feature -- Status setting set_cursor_visibility (a_value: BOOLEAN) is -- If `a_value' is `True' make cursor visible, -- else make it invisible. require video_subsystem_enabled: is_enabled local i: INTEGER do if a_value then i := sdl_show_cursor_external (Em_enable) else i := sdl_show_cursor_external (Em_disable) end end show_cursor is -- Make mouse cursor visible. require video_subsystem_enabled: is_enabled do set_cursor_visibility (True) end hide_cursor is -- Make mouse cursor invisible. require video_subsystem_enabled: is_enabled do set_cursor_visibility (False) end toggle_cursor_visibility is -- Make mouse cursor visible if it was previously invisible and vice versa. require video_subsystem_enabled: is_enabled do if is_cursor_visible then hide_cursor else show_cursor end end feature -- Element change set_video_surface_width (a_width: INTEGER) is -- Set the video surface width to `a_width'. do video_surface_width := a_width ensure width_set: video_surface_width = a_width end set_video_surface_height (a_height: INTEGER) is -- Set the video surface height to `a_height'. do video_surface_height := a_height ensure height_set: video_surface_height = a_height end set_video_bpp (a_resolution: INTEGER) is -- Set the video surface bits per pixel to `a_resolution'. -- a_resolution of 24 is a lot slower than 8, 16 or 32. do video_surface_bpp := a_resolution ensure bpp_set: video_surface_bpp = a_resolution end feature -- Video subsystem flags -- The flags below are relevant for sdl_set_video_mode_external used above -- AND for sdl_createRGBSurface_external not used until now. software_surface: BOOLEAN -- Is the displayed surface in system memory? hardware_surface: BOOLEAN -- Is the displayed surface in video memory? async_blit: BOOLEAN -- Does the video subsystem use asynchronous blits if it is possible? -- This can speed up blitting on multiple CPU machines or SMP systems. -- The flags below are relevant for sdl_set_video_mode_external used above. anyformat: BOOLEAN -- Should the video subsystem be forced to use -- a given surface even if the requested bits per pixel are not available? hwpalette: BOOLEAN -- Does the video subsystem have access to the hard ware palette? doublebuffered: BOOLEAN -- Does the video subsystem use doublebuffering? multisampled: BOOLEAN -- Does the video subsystem use multisampling? fullscreen: BOOLEAN -- Does the video subsystem use fullscreen? opengl: BOOLEAN -- Is opengl enabled without OpenGL video attributes? resizeable: BOOLEAN -- Is the window created by the video subsystem resizeable? noframe: BOOLEAN -- Does the window created have no frame? set_software_surface (a_boolean: BOOLEAN) is -- Is the displayed surface in system memory. do set_doublebuffered (False) software_surface := a_boolean hardware_surface := not a_boolean ensure no_double_buffering: doublebuffered = False software_surface_set: software_surface = a_boolean end set_hardware_surface (a_boolean: BOOLEAN) is -- Is the displayed surface in video memory. do software_surface := not a_boolean hardware_surface := a_boolean ensure hardware_surface_set: hardware_surface = a_boolean end set_async_blit (a_boolean: BOOLEAN) is -- Does the video subsystem use asynchronous blits if it is possible. -- This can speed up blitting on multiple CPU machines or SMP systems. do async_blit := a_boolean ensure async_blit_set: async_blit = a_boolean end set_anyformat (a_boolean: BOOLEAN) is -- Force the video subsystem to display -- a surface even if it's bpp is not available. do anyformat := a_boolean ensure anyformat_set: anyformat = a_boolean end set_hwpalette (a_boolean: BOOLEAN) is -- Grant the video subsystem access to the hardware palette. do hwpalette := a_boolean ensure hwpalette_set: hwpalette = a_boolean end set_doublebuffered (a_boolean: BOOLEAN) is -- Use doublebuffering. do set_hardware_surface (True) doublebuffered := a_boolean ensure --use_hardware_surface: hardware_surface = True doublebuffered_set: doublebuffered = a_boolean end set_multisampled (a_boolean: BOOLEAN) is -- Use multisampling. do set_hardware_surface (True) multisampled := a_boolean ensure --use_hardware_surface: hardware_surface = True multisampled_set: multisampled = a_boolean end set_fullscreen (a_boolean: BOOLEAN) is -- Use fullscreen. This yields only good results if your -- display server (Xserver or Graphics driver for example) -- supports the format. -- Example: You have a surface that mesures 800x600 pixels -- and your display server supports 800x600 as a resolution. -- Counter example: You have a 700x500 surface, but your -- display server only supports 800x600, the surface will be displayed -- but there will be an edge around the surface that won't be accessible. do fullscreen := a_boolean ensure fullscreen_set: fullscreen = a_boolean end set_opengl (a_boolean: BOOLEAN) is -- Enable OpenGL without video attributes. do opengl := a_boolean ensure opengl_set: opengl = a_boolean end set_resizeable (a_boolean: BOOLEAN) is -- Create a resizeable window. When the window is -- resizes an resize_event is fired and the -- sdl_set_video_mode_external can be set with the new size. -- You will need to register an event handler in the event loop -- in order to do this. do resizeable := a_boolean ensure resizeable_set: resizeable = a_boolean end set_noframe (a_boolean: BOOLEAN) is -- Display the surface without frame. -- Note: Fullscreen mode have this flag set -- automatically. do noframe := a_boolean ensure noframe_set: noframe = a_boolean end feature -- Video subsystem OpenGL binding -- this are the attributes for the openGL mode gl_red_size: INTEGER -- Red framebuffer size gl_green_size: INTEGER -- Green framebuffer size gl_blue_size: INTEGER -- Blue framebuffer size gl_alpha_size: INTEGER -- Alpha framebuffer size gl_accum_red_size: INTEGER -- Red accumulator size gl_accum_green_size: INTEGER -- Green accumulator size gl_accum_blue_size: INTEGER -- Blue accumulator size gl_accum_alpha_size: INTEGER -- Alpha accumulator size gl_buffer_size: INTEGER -- Framebuffer size gl_depth_size: INTEGER -- Depth buffer size gl_stencil_size: INTEGER -- Stencil buffer size gl_multisample_buffers : INTEGER -- Number of multisample buffers gl_multisample_samples : INTEGER -- Number of multisample samples gl_set_color_size_framebuffer ( r: INTEGER; g: INTEGER; b: INTEGER; a: INTEGER) is -- Set framebuffer color sizes. do gl_red_size := r gl_green_size := g gl_blue_size := b gl_alpha_size := a ensure gl_red_size_set: gl_red_size = r gl_green_size_set: gl_green_size = g gl_blue_size_set: gl_blue_size = b gl_alpha_size_set: gl_alpha_size = a end gl_set_color_size_accum ( r: INTEGER; g: INTEGER; b: INTEGER; a: INTEGER) is -- Set accumulator color sizes. do gl_accum_red_size := r gl_accum_green_size := g gl_accum_blue_size := b gl_accum_alpha_size := a ensure gl_accum_red_size_set: gl_accum_red_size = r gl_accum_green_size_set: gl_accum_green_size = g gl_accum_blue_size_set: gl_accum_blue_size = b gl_accum_alpha_size_set: gl_accum_alpha_size = a end gl_set_buffer_size ( an_integer: INTEGER ) is -- Set framebuffer size. do gl_buffer_size := an_integer ensure gl_buffer_size_set: gl_buffer_size = an_integer end gl_set_depth_size ( an_integer: INTEGER ) is -- Set depth buffer size. do gl_depth_size := an_integer ensure gl_depth_size_set: gl_depth_size = an_integer end gl_set_stencil_size ( an_integer: INTEGER ) is -- Set stencil buffer size. do gl_stencil_size := an_integer ensure gl_stencil_size_set: gl_stencil_size = an_integer end gl_set_multisample_buffers ( an_integer: INTEGER ) is -- Set the number of multisample buffers do gl_multisample_buffers := an_integer ensure gl_multisample_buffers = an_integer end gl_set_multisample_samples ( an_integer: INTEGER ) is -- Set the number of multisample samples do gl_multisample_samples := an_integer ensure gl_multisample_samples = an_integer end opengl_enabled: BOOLEAN is -- Is the OpenGL mode activated? do Result := opengl end feature {NONE} -- Implementation opengl_set_attributes is -- Set the openGL attributes local returnval: INTEGER do if doublebuffered then returnval := sdl_gl_set_attribute_external (sdl_gl_doublebuffer, 1) else returnval := sdl_gl_set_attribute_external (sdl_gl_doublebuffer, 0) end if multisampled then returnval := returnval + sdl_gl_set_attribute_external (sdl_gl_multisamplebuffers, gl_multisample_buffers) returnval := returnval + sdl_gl_set_attribute_external (sdl_gl_multisamplesamples, gl_multisample_samples) end returnval := returnval + sdl_gl_set_attribute_external (sdl_gl_red_size, gl_red_size) returnval := returnval + sdl_gl_set_attribute_external (sdl_gl_green_size, gl_green_size) returnval := returnval + sdl_gl_set_attribute_external (sdl_gl_blue_size, gl_blue_size) returnval := returnval + sdl_gl_set_attribute_external (sdl_gl_alpha_size, gl_alpha_size) returnval := returnval + sdl_gl_set_attribute_external (sdl_gl_accum_red_size, gl_accum_red_size) returnval := returnval + sdl_gl_set_attribute_external (sdl_gl_accum_green_size, gl_accum_green_size) returnval := returnval + sdl_gl_set_attribute_external (sdl_gl_accum_blue_size, gl_accum_blue_size) returnval := returnval + sdl_gl_set_attribute_external (sdl_gl_accum_alpha_size, gl_accum_alpha_size) returnval := returnval + sdl_gl_set_attribute_external (sdl_gl_buffer_size, gl_buffer_size) returnval := returnval + sdl_gl_set_attribute_external (sdl_gl_depth_size, gl_depth_size) returnval := returnval + sdl_gl_set_attribute_external (sdl_gl_stencil_size, gl_stencil_size) check attributes_set_correctly: returnval = 0 end end video_surface_flags: INTEGER is -- Calculate the video flags from the video subsystem attributes. do Result := 0x00000000 if software_surface then Result := Result | Em_software_surface end if hardware_surface then Result := Result | Em_hardware_surface end if async_blit then Result := Result | Em_async_blit end if anyformat then Result := Result | Em_anyformat end if hwpalette then Result := Result | Em_hwpalette end if doublebuffered then Result := Result | Em_doublebuffered end if fullscreen then Result := Result | Em_video_fullscreen end if opengl then Result := Result | Em_opengl end if resizeable then Result := Result | Em_resizeable end if noframe then Result := Result | Em_noframe end end invariant valid_video_surface: is_enabled implies (video_surface /= Void) end