note
	description: "[
		i_video.c
		DOOM graphics stuff for SDL library
	]"
	license: "[
		Copyright (C) 1993-1996 by id Software, Inc.
		Copyright (C) 2005-2014 Simon Howard
		Copyright (C) 2021 Ilgiz Mustafin
		
		This program is free software; you can redistribute it and/or modify
		it under the terms of the GNU General Public License as published by
		the Free Software Foundation; either version 2 of the License, or
		(at your option) any later version.
		
		This program is distributed in the hope that it will be useful,
		but WITHOUT ANY WARRANTY; without even the implied warranty of
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
		GNU General Public License for more details.
		
		You should have received a copy of the GNU General Public License along
		with this program; if not, write to the Free Software Foundation, Inc.,
		51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
	]"

class 
	I_VIDEO

create 
	make

feature 

	i_main: I_MAIN

	make (a_i_main: like i_main)
		do
			i_main := a_i_main
			firsttime := True
			multiply := 1
			aspect_ratio_correct := True
			window_width := 800
			window_height := 600
			fullscreen := False
			create i_videobuffer.make (1)
			window_focused := True
			grabmouse := 1
			nomouse := i_main.m_argv.m_checkparm ("-nomouse").to_boolean
		end
	
feature 

	Screenheight_4_3: INTEGER_32 = 240
	
feature 

	multiply: INTEGER_32

	screen: detachable SDL_WINDOW_STRUCT_API

	renderer: detachable SDL_RENDERER_STRUCT_API

	texture: detachable SDL_TEXTURE_STRUCT_API

	texture_upscaled: detachable SDL_TEXTURE_STRUCT_API

	screenbuffer: detachable SDL_SURFACE_STRUCT_API

	argbbuffer: detachable SDL_SURFACE_STRUCT_API

	pixel_format: NATURAL_32
	
feature 

	fullscreen: BOOLEAN

	screensaver_mode: BOOLEAN

	Fullscreen_width: INTEGER_32 = 0

	Fullscreen_height: INTEGER_32 = 0
	
feature 

	Startup_delay: INTEGER_32 = 1000
			-- Time to wait for the screen to settle on startup before starting the
			-- game (ms)
	
feature -- Aspect ratio correction mode

	aspect_ratio_correct: BOOLEAN

	integer_scaling: BOOLEAN
			-- Force integer scales for resolution-independent rendering

	actualheight: INTEGER_32

	Max_scaling_buffer_pixels: INTEGER_32 = 16000000
	
feature 

	initialized: BOOLEAN

	Screenvisible: BOOLEAN = True
	
feature 

	Usemouse: BOOLEAN = True

	nomouse: BOOLEAN
	
feature 

	window_focused: BOOLEAN
	
feature 

	i_videobuffer: PIXEL_T_BUFFER
			--  The screen buffer; this is modified to draw things to the screen
	
feature 

	Blit_rect: SDL_RECT_STRUCT_API
		once
			create Result.make
			Result.set_x (0)
			Result.set_y (0)
			Result.set_w ({DOOMDEF_H}.screenwidth)
			Result.set_h ({DOOMDEF_H}.screenheight)
		end
	
feature 

	Palette: ARRAY [SDL_COLOR_STRUCT_API]
		local
			i: INTEGER_32
		once
			create Result.make_filled (create {SDL_COLOR_STRUCT_API}.make, 0, 255)
			from
				i := Result.lower
			until
				i > Result.upper
			loop
				Result [i] := create {SDL_COLOR_STRUCT_API}.make
				i := i + 1
			end
		end

	palette_to_set: BOOLEAN
	
feature -- Screen width and height, from configuration file.

	window_width: INTEGER_32

	window_height: INTEGER_32
	
feature -- I_InitGraphics

	firsttime: BOOLEAN

	i_initgraphics
			-- from https://github.com/chocolate-doom/chocolate-doom/blob/7a0db31614ec187e363e7664036d95ec56242e44/src/i_video.c#L1357
		local
			dummy: SDL_EVENT_UNION_API
		do
			{NOT_IMPLEMENTED}.not_implemented ("I_InitGraphics", False)
			if {SDL_FUNCTIONS_API}.sdl_init ({SDL_CONSTANT_API}.sdl_init_video.to_natural_32) < 0 then
				{I_MAIN}.i_error ("Failed to initialize video: " + {SDL_ERROR}.sdl_get_error)
			end
			if aspect_ratio_correct then
				actualheight := Screenheight_4_3
			else
				actualheight := {DOOMDEF_H}.screenheight
			end
			adjust_window_size
			set_video_mode
			check
					attached screenbuffer as sb
			then
				if {SDL_SURFACE}.sdl_fill_rect (sb, Void, 0) < 0 then
					{I_MAIN}.i_error ("SDL_FillRect failed " + {SDL_ERROR}.sdl_get_error)
				end
			end
			i_setpalette (i_main.W_wad.w_cachelumpname ("PLAYPAL"))
			set_sdl_palette
			updategrab
			if fullscreen and not screensaver_mode then
				{SDL_TIMER_FUNCTIONS_API}.sdl_delay (Startup_delay.to_natural_32)
			end
			check
					attached screenbuffer as sb
			then
				create i_videobuffer.share_from_pointer (sb.pixels, {DOOMDEF_H}.screenwidth * {DOOMDEF_H}.screenheight)
			end
			i_main.V_video.v_restorebuffer
			i_videobuffer.fill_zero
			from
				create dummy.make
			until
				{SDL_EVENTS}.sdl_poll_event (dummy) = 0
			loop
			end
			initialized := True
		end

	adjust_window_size
			-- Adjust window_width / window_height variables to be an an aspect
			-- ratio consistent with the aspect_ratio_correct variable.
		do
			if aspect_ratio_correct or integer_scaling then
				if window_width * actualheight <= window_height * {DOOMDEF_H}.screenwidth then
					window_height := (window_width * actualheight + {DOOMDEF_H}.screenwidth - 1) // {DOOMDEF_H}.screenwidth
				else
					window_width := window_height * {DOOMDEF_H}.screenwidth // actualheight
				end
			end
		end
	
feature 

	i_startframe
		do
		end

	i_starttic
		do
			{NOT_IMPLEMENTED}.not_implemented ("I_StartTic", False)
			if initialized then
				i_getevent
				if Usemouse and not nomouse and window_focused then
					i_main.I_input.i_readmouse
				end
			end
		end

	i_getevent
		local
			event: EVENT_T
			sdl_event: SDL_EVENT_UNION_API
		do
			from
				{SDL_EVENTS_FUNCTIONS_API}.sdl_pump_events
				create sdl_event.make
			until
				{SDL_EVENTS_FUNCTIONS_API}.sdl_poll_event (sdl_event) = 0
			loop
				if sdl_event.type = {SDL_CONSTANT_API}.sdl_keydown and then toggle_full_screen_key_shortcut (sdl_event.key.keysym) then
					i_togglefullscreen
				elseif sdl_event.type = {SDL_CONSTANT_API}.sdl_keydown or sdl_event.type = {SDL_CONSTANT_API}.sdl_keyup then
					i_main.I_input.i_handlekeyboardevent (sdl_event)
				elseif sdl_event.type = {SDL_CONSTANT_API}.sdl_mousebuttondown or sdl_event.type = {SDL_CONSTANT_API}.sdl_mousebuttonup or sdl_event.type = {SDL_CONSTANT_API}.sdl_mousewheel then
					if Usemouse and not nomouse and window_focused then
						i_main.I_input.i_handlemouseevent (sdl_event)
					end
				elseif sdl_event.type = {SDL_CONSTANT_API}.sdl_quit then
					if screensaver_mode then
						i_main.I_system.i_quit
					else
						create event.make
						event.type := {EVENT_T}.ev_quit
						i_main.D_main.d_postevent (event)
					end
				elseif sdl_event.type = {SDL_CONSTANT_API}.sdl_windowevent then
					check
							attached screen as s
					then
						if sdl_event.window.windowid = {SDL_VIDEO_FUNCTIONS_API}.sdl_get_window_id (s) then
							handlewindowevent (sdl_event.window)
						end
					end
				end
			end
		end

	toggle_full_screen_key_shortcut (sym: SDL_KEYSYM_STRUCT_API): BOOLEAN
		local
			flags: NATURAL_32
		do
			flags := {SDL_KEYMOD_ENUM_API}.kmod_lalt.as_natural_32 | {SDL_KEYMOD_ENUM_API}.kmod_ralt.as_natural_32
			Result := (sym.scancode = {SDL_SCANCODE_ENUM_API}.sdl_scancode_return or sym.scancode = {SDL_SCANCODE_ENUM_API}.sdl_scancode_kp_enter) and ((sym.mod & flags) /= 0)
		end

	i_togglefullscreen
		local
			flags: INTEGER_32
		do
			if Fullscreen_width /= 0 or Fullscreen_height /= 0 then
			else
				fullscreen := not fullscreen
				if fullscreen then
					flags := flags | {SDL_WINDOW_FLAGS_ENUM_API}.sdl_window_fullscreen_desktop
				end
				check
						attached screen as s
				then
					{SDL_VIDEO_FUNCTIONS_API}.sdl_set_window_fullscreen (s, flags.as_natural_32).do_nothing
					if not fullscreen then
						adjustwindowsize
						{SDL_VIDEO_FUNCTIONS_API}.sdl_set_window_size (s, window_width, window_height)
					end
				end
			end
		end

	adjustwindowsize
			-- Adjust window_width / window_height variables to be an aspect
			-- ratio consistent with the aspect_ratio_correct variable.
		do
			if aspect_ratio_correct or integer_scaling then
				if window_width * actualheight <= window_height * {DOOMDEF_H}.screenwidth then
					window_height := (window_width * actualheight + {DOOMDEF_H}.screenwidth - 1) // {DOOMDEF_H}.screenwidth
				else
					window_width := window_height * {DOOMDEF_H}.screenwidth // actualheight
				end
			end
		end

	handlewindowevent (event: SDL_WINDOW_EVENT_STRUCT_API)
		do
			{NOT_IMPLEMENTED}.not_implemented ("HandleWindowEvent", False)
			if event.type = {SDL_WINDOW_EVENT_ID_ENUM_API}.sdl_windowevent_focus_gained.as_natural_32 then
				window_focused := True
			elseif event.type = {SDL_WINDOW_EVENT_ID_ENUM_API}.sdl_windowevent_focus_lost.as_natural_32 then
				window_focused := False
			end
		end
	
feature 

	i_readscreen (scr: PIXEL_T_BUFFER)
		do
			scr.copy_from (i_videobuffer)
		end
	
feature 

	i_updatenoblit
		do
		end
	
feature 

	set_video_mode
			-- from https://github.com/chocolate-doom/chocolate-doom/blob/7a0db31614ec187e363e7664036d95ec56242e44/src/i_video.c#L1149
		local
			bpp: INTEGER_32
			rmask: NATURAL_32
			gmask: NATURAL_32
			bmask: NATURAL_32
			amask: NATURAL_32
			p: POINTER
			w, h: INTEGER_32
			window_flags, renderer_flags: INTEGER_32
		do
			{NOT_IMPLEMENTED}.not_implemented ("set_video_mode", False)
			w := window_width
			h := window_height
			window_flags := {SDL_WINDOW_FLAGS_ENUM_API}.sdl_window_resizable
			window_flags := window_flags | {SDL_WINDOW_FLAGS_ENUM_API}.sdl_window_allow_highdpi
			if fullscreen then
				if Fullscreen_width = 0 and Fullscreen_height = 0 then
					window_flags := window_flags | {SDL_WINDOW_FLAGS_ENUM_API}.sdl_window_fullscreen_desktop
				else
					w := Fullscreen_width
					h := Fullscreen_height
					window_flags := window_flags | {SDL_WINDOW_FLAGS_ENUM_API}.sdl_window_fullscreen
				end
			end
			if screen = Void then
				screen := {SDL_VIDEO}.sdl_create_window ("SDL EIFFEL DOOM", {SDL_CONSTANT_API}.sdl_windowpos_undefined, {SDL_CONSTANT_API}.sdl_windowpos_undefined, w, h, window_flags.to_natural_32)
				if screen = Void then
					{I_MAIN}.i_error ("Error creating window for video startup" + {SDL_ERROR}.sdl_get_error)
				end
				check
						attached screen as s
				then
					pixel_format := {SDL_VIDEO}.sdl_get_window_pixel_format (s)
				end
			end
			renderer_flags := {SDL_RENDERER_FLAGS_ENUM_API}.sdl_renderer_targettexture
			if attached renderer as r then
				{SDL_RENDER_FUNCTIONS_API}.sdl_destroy_renderer (r)
				texture := Void
				texture_upscaled := Void
			end
			check
					attached screen as s
			then
				renderer := {SDL_RENDER_FUNCTIONS_API}.sdl_create_renderer (s, -1, renderer_flags.to_natural_32)
			end
			if renderer = Void then
				{I_MAIN}.i_error ("Error creating renderer for screen window " + {SDL_ERROR}.sdl_get_error)
			end
			check
					attached renderer as r
			then
				if aspect_ratio_correct or integer_scaling then
					if {SDL_RENDER_FUNCTIONS_API}.sdl_render_set_logical_size (r, {DOOMDEF_H}.screenwidth, actualheight) /= 0 then
						{I_MAIN}.i_error ("Error setting logical size " + {SDL_ERROR}.sdl_get_error)
					end
				end
				if {SDL_RENDER_FUNCTIONS_API}.sdl_render_set_integer_scale (r, if integer_scaling then
						1
					else
						0
					end) /= 0 then
					{I_MAIN}.i_error ("Error setting integer scale " + {SDL_ERROR}.sdl_get_error)
				end
				if {SDL_RENDER_FUNCTIONS_API}.sdl_set_render_draw_color (r, (0).to_character_8, (0).to_character_8, (0).to_character_8, (255).to_character_8) /= 0 then
					{I_MAIN}.i_error ("Error setting render color " + {SDL_ERROR}.sdl_get_error)
				end
				if {SDL_RENDER_FUNCTIONS_API}.sdl_render_clear (r) /= 0 then
					{I_MAIN}.i_error ("Error render clear " + {SDL_ERROR}.sdl_get_error)
				end
				{SDL_RENDER_FUNCTIONS_API}.sdl_render_present (r)
			end
			if attached screenbuffer as sb then
				{SDL_SURFACE_FUNCTIONS_API}.sdl_free_surface (sb)
				screenbuffer := Void
			end
			if screenbuffer = Void then
				create screenbuffer.make_by_pointer ({SDL_SURFACE_FUNCTIONS_API}.sdl_create_rgbsurface (0, {DOOMDEF_H}.screenwidth, {DOOMDEF_H}.screenheight, 8, 0, 0, 0, 0))
				check
						attached screenbuffer as sb
				then
					if {SDL_SURFACE}.sdl_fill_rect (sb, Void, 0) < 0 then
						i_main.i_error ("Error SDL_FillRect" + {SDL_ERROR}.sdl_get_error)
					end
				end
			end
			if attached argbbuffer as abb then
				{SDL_SURFACE_FUNCTIONS_API}.sdl_free_surface (abb)
				argbbuffer := Void
			end
			if argbbuffer = Void then
				if {SDL_PIXELS_FUNCTIONS_API}.sdl_pixel_format_enum_to_masks (pixel_format, $bpp, $rmask.to_pointer, $gmask.to_pointer, $bmask.to_pointer, $amask.to_pointer).to_integer_64 /= {SDL_CONSTANT_API}.sdl_true then
					i_main.i_error ("pixel format to masks " + {SDL_ERROR}.sdl_get_error)
				end
				p := {SDL_SURFACE_FUNCTIONS_API}.sdl_create_rgbsurface (0, {DOOMDEF_H}.screenwidth, {DOOMDEF_H}.screenheight, bpp, rmask, gmask, bmask, amask)
				if p.is_default_pointer then
					i_main.i_error ("SDL_CreateRGBSurface failed" + {SDL_ERROR}.sdl_get_error)
				else
					create argbbuffer.make_by_pointer (p)
				end
				check
						attached argbbuffer as abb
				then
					if {SDL_SURFACE}.sdl_fill_rect (abb, Void, 0) < 0 then
						i_main.i_error ("Error SDL_FillRect" + {SDL_ERROR}.sdl_get_error)
					end
				end
			end
			if attached texture as t then
				{SDL_RENDER_FUNCTIONS_API}.sdl_destroy_texture (t)
			end
			if not {SDL_HINTS}.sdl_set_hint ({SDL_CONSTANT_API}.sdl_hint_render_scale_quality, "nearest") then
				{I_MAIN}.i_error ("Error setting hint " + {SDL_ERROR}.sdl_get_error)
			end
			check
					attached renderer as r
			then
				texture := {SDL_RENDER}.sdl_create_texture (r, pixel_format, {SDL_TEXTURE_ACCESS_ENUM_API}.sdl_textureaccess_streaming, {DOOMDEF_H}.screenwidth, {DOOMDEF_H}.screenheight)
			end
			create_upscaled_texture (True)
		end
	
feature -- CreateUpscaledTexture

	h_upscale_old: INTEGER_32

	w_upscale_old: INTEGER_32

	create_upscaled_texture (force: BOOLEAN)
		local
			w, h: INTEGER_32
			h_upscale, w_upscale: INTEGER_32
			new_texture, old_texture: SDL_TEXTURE_STRUCT_API
			b: BOOLEAN
		do
			check
					attached renderer as r
			then
				if {SDL_RENDER_FUNCTIONS_API}.sdl_get_renderer_output_size (r, $w, $h) /= 0 then
					{I_MAIN}.i_error ("Failed to get renderer output size " + {SDL_ERROR}.sdl_get_error)
				end
			end
			if w * actualheight < h * {DOOMDEF_H}.screenwidth then
				h := w * actualheight // {DOOMDEF_H}.screenwidth
			else
				w := h * {DOOMDEF_H}.screenwidth // actualheight
			end
			w_upscale := (w + {DOOMDEF_H}.screenwidth - 1) // {DOOMDEF_H}.screenwidth
			h_upscale := (h + {DOOMDEF_H}.screenheight - 1) // {DOOMDEF_H}.screenheight
			if w_upscale < 1 then
				w_upscale := 1
			end
			if h_upscale < 1 then
				h_upscale := 1
			end
			limit_texture_size ($w_upscale, $h_upscale)
			if (h_upscale = h_upscale_old and w_upscale = w_upscale_old and not force) then
			else
				h_upscale_old := h_upscale
				w_upscale_old := w_upscale
				b := {SDL_HINTS}.sdl_set_hint ({SDL_CONSTANT_API}.sdl_hint_render_scale_quality, "linear")
				check
						attached renderer as r
				then
					new_texture := {SDL_RENDER_FUNCTIONS_API}.sdl_create_texture (r, pixel_format, {SDL_TEXTURE_ACCESS_ENUM_API}.sdl_textureaccess_target, w_upscale * {DOOMDEF_H}.screenwidth, h_upscale * {DOOMDEF_H}.screenheight)
					old_texture := texture_upscaled
					texture_upscaled := new_texture
					if attached old_texture as ot then
						{SDL_RENDER_FUNCTIONS_API}.sdl_destroy_texture (ot)
					end
				end
			end
		end

	limit_texture_size (w_upscale, h_upscale: TYPED_POINTER [INTEGER_32])
		local
			rinfo: SDL_RENDERER_INFO_STRUCT_API
			orig_w, orig_h: INTEGER_32
			mp_w, mp_h: MANAGED_POINTER
		do
			create rinfo.make
			create mp_w.share_from_pointer (w_upscale.to_pointer, {PLATFORM}.integer_32_bytes)
			orig_w := mp_w.read_integer_32 (0)
			create mp_h.share_from_pointer (h_upscale.to_pointer, {PLATFORM}.integer_32_bytes)
			orig_h := mp_h.read_integer_32 (0)
			check
					attached renderer as r
			then
				if {SDL_RENDER_FUNCTIONS_API}.sdl_get_renderer_info (r, rinfo) /= 0 then
					{I_MAIN}.i_error ("CreateUpscaledTexture: SDL_GetRendererInfo() call failed " + {SDL_ERROR}.sdl_get_error)
				end
			end
			from
			until
				mp_w.read_integer_32 (0) * {DOOMDEF_H}.screenwidth <= rinfo.max_texture_width
			loop
				mp_w.put_integer_32 (mp_w.read_integer_32 (0) - 1, 0)
			end
			from
			until
				mp_h.read_integer_32 (0) * {DOOMDEF_H}.screenheight <= rinfo.max_texture_height
			loop
				mp_h.put_integer_32 (mp_h.read_integer_32 (0) - 1, 0)
			end
			if (mp_w.read_integer_32 (0) < 1 and rinfo.max_texture_width > 0) or (mp_h.read_integer_32 (0) < 1 and rinfo.max_texture_height > 0) then
				{I_MAIN}.i_error ("[
						CreateUpscaledTexture: Can't create a texture big enough for
						the whole screen! Maximum texture size
					]" + rinfo.max_texture_width.out + "x" + rinfo.max_texture_height.out)
			end
			if (Max_scaling_buffer_pixels < {DOOMDEF_H}.screenwidth * {DOOMDEF_H}.screenheight) then
				{I_MAIN}.i_error ("[
						CreateUpscaledTexture: max_scaling_buffer_pixels too small
						        to create a texture buffer:
					]" + Max_scaling_buffer_pixels.out + " < " + ({DOOMDEF_H}.screenwidth * {DOOMDEF_H}.screenheight).out)
			end
			from
			until
				(mp_w.read_integer_32 (0) * mp_h.read_integer_32 (0) * {DOOMDEF_H}.screenwidth * {DOOMDEF_H}.screenheight) <= Max_scaling_buffer_pixels
			loop
				if mp_w.read_integer_32 (0) > mp_h.read_integer_32 (0) then
					mp_w.put_integer_32 (mp_w.read_integer_32 (0) - 1, 0)
				else
					mp_h.put_integer_32 (mp_h.read_integer_32 (0) - 1, 0)
				end
			end
			if mp_w.read_integer_32 (0) /= orig_w or mp_h.read_integer_32 (0) /= orig_h then
				print ("CreateUpscaledTexture: Limited texture size to " + (mp_w.read_integer_32 (0) * {DOOMDEF_H}.screenwidth).out + "x" + (mp_h.read_integer_32 (0) * {DOOMDEF_H}.screenheight).out)
			end
		end
	
feature -- I_FinishUpdate

	lasttic: INTEGER_32

	i_finishupdate
		do
			{NOT_IMPLEMENTED}.not_implemented ("I_FinishUpdate", False)
			updategrab
			check
					attached screenbuffer as sb
			then
				if palette_to_set then
					check
							attached sb.format as f and then attached f.palette as p
					then
						set_sdl_palette
						palette_to_set := False
					end
				end
			end
			check
					attached screenbuffer as sb and then attached argbbuffer as abb and then attached texture as t
			then
				check
						attached renderer as r and then attached texture_upscaled as tu
				then
					if {SDL_SURFACE_FUNCTIONS_API}.sdl_lower_blit (sb, Blit_rect, abb, Blit_rect) < 0 then
						i_main.i_error ("From 8bit blit error " + {SDL_ERROR}.sdl_get_error)
					end
					if {SDL_RENDER}.sdl_update_texture (t, Void, abb.pixels, abb.pitch) < 0 then
						i_main.i_error ("Upd intermediate with RGBA buffer " + {SDL_ERROR}.sdl_get_error)
					end
					if {SDL_RENDER_FUNCTIONS_API}.sdl_render_clear (r) < 0 then
						i_main.i_error ("render clear " + {SDL_ERROR}.sdl_get_error)
					end
					if {SDL_RENDER}.sdl_set_render_target (r, tu) < 0 then
						i_main.i_error ("render target " + {SDL_ERROR}.sdl_get_error)
					end
					if {SDL_RENDER}.sdl_render_copy (r, t, Void, Void) < 0 then
						i_main.i_error ("render copy " + {SDL_ERROR}.sdl_get_error)
					end
					if {SDL_RENDER}.sdl_set_render_target (r, Void) < 0 then
						i_main.i_error ("render target " + {SDL_ERROR}.sdl_get_error)
					end
					if {SDL_RENDER}.sdl_render_copy (r, tu, Void, Void) < 0 then
						i_main.i_error ("render copy " + {SDL_ERROR}.sdl_get_error)
					end
					{SDL_RENDER_FUNCTIONS_API}.sdl_render_present (r)
				end
			end
		end
	
feature -- Mouse grab

	currently_grabbed: BOOLEAN

	nograbmouse_override: BOOLEAN

	grabmouse: INTEGER_32

	grabmouse_callback: detachable PREDICATE assign set_grabmouse_callback

	set_grabmouse_callback (a_grabmouse_callback: like grabmouse_callback)
		do
			grabmouse_callback := a_grabmouse_callback
		end

	mouseshouldbegrabbed: BOOLEAN
		do
			if screensaver_mode then
				Result := False
			elseif not window_focused then
				Result := False
			elseif fullscreen then
				Result := True
			elseif not Usemouse or nomouse then
				Result := False
			elseif nograbmouse_override or not grabmouse.to_boolean then
				Result := False
			elseif attached grabmouse_callback as cb then
				Result := cb.item
			else
				Result := True
			end
		end

	updategrab
		local
			grab: BOOLEAN
			screen_w, screen_h: INTEGER_32
		do
			grab := mouseshouldbegrabbed
			if screensaver_mode then
				setshowcursor (False)
			elseif grab and not currently_grabbed then
				setshowcursor (False)
			elseif not grab and currently_grabbed then
				setshowcursor (True)
				check
						attached screen as s
				then
					{SDL_VIDEO_FUNCTIONS_API}.sdl_get_window_size (s, $screen_w, $screen_h)
					{SDL_MOUSE_FUNCTIONS_API}.sdl_warp_mouse_in_window (s, screen_w - 16, screen_h - 16)
				end
				{SDL_MOUSE_FUNCTIONS_API}.sdl_get_relative_mouse_state (create {TYPED_POINTER [INTEGER_32]}, create {TYPED_POINTER [INTEGER_32]}).do_nothing
			end
			currently_grabbed := grab
		end

	setshowcursor (show: BOOLEAN)
		do
			if not screensaver_mode then
				{SDL_MOUSE_FUNCTIONS_API}.sdl_set_relative_mouse_mode ((not show).to_integer).do_nothing
				{SDL_MOUSE_FUNCTIONS_API}.sdl_get_relative_mouse_state (create {TYPED_POINTER [INTEGER_32]}, create {TYPED_POINTER [INTEGER_32]}).do_nothing
			end
		end
	
feature 

	i_setpalette (doompalette: MANAGED_POINTER)
			-- originally took void* palette
			-- from https://github.com/chocolate-doom/chocolate-doom/blob/7a0db31614ec187e363e7664036d95ec56242e44/src/i_video.c#L822
		local
			i: INTEGER_32
			d: INTEGER_32
			not_3: NATURAL_8
		do
			not_3 := (3).to_natural_8.bit_not
			from
				i := 0
				d := 0
			until
				i >= 256
			loop
				Palette [i].set_r ((i_main.V_video.Gammatable [i_main.V_video.usegamma] [doompalette.read_natural_8_le (d).to_integer_32 + 1] & not_3).to_character_8)
				d := d + 1;
				Palette [i].set_g ((i_main.V_video.Gammatable [i_main.V_video.usegamma] [doompalette.read_natural_8_le (d).to_integer_32 + 1] & not_3).to_character_8)
				d := d + 1;
				Palette [i].set_b ((i_main.V_video.Gammatable [i_main.V_video.usegamma] [doompalette.read_natural_8_le (d).to_integer_32 + 1] & not_3).to_character_8)
				d := d + 1
				i := i + 1
			end
			palette_to_set := True
		end

	set_sdl_palette
		local
			mp: MANAGED_POINTER
			i: INTEGER_32
		do
			check
					attached screenbuffer as sb and then attached sb.format as f and then attached f.palette as p
			then
				create mp.make (256 * 4)
				from
					i := 0
				until
					i >= 256
				loop
					mp.put_natural_8 (Palette [i].r.code.to_natural_8, 4 * i + 0)
					mp.put_natural_8 (Palette [i].g.code.to_natural_8, 4 * i + 1)
					mp.put_natural_8 (Palette [i].b.code.to_natural_8, 4 * i + 2)
					mp.put_natural_8 (Palette [i].a.code.to_natural_8, 4 * i + 3)
					i := i + 1
				end
				if {SDL_PIXELS_FUNCTIONS_API}.c_sdl_set_palette_colors (p.item, mp.item, 0, 256) < 0 then
					{I_MAIN}.i_error ("SDL_SetPaletteColors failed " + {SDL_ERROR}.sdl_get_error)
				end
			end
		end
	
end -- class I_VIDEO

Generated by ISE EiffelStudio