예제 #1
0
void sdl_window_info::update()
{
	osd_ticks_t     event_wait_ticks;
	ASSERT_MAIN_THREAD();

	// adjust the cursor state
	//sdlwindow_update_cursor_state(machine, window);

	auto wp = std::make_unique<worker_param>(std::static_pointer_cast<sdl_window_info>(shared_from_this()));
	execute_async(&update_cursor_state_wt, std::move(wp));

	// if we're visible and running and not in the middle of a resize, draw
	if (m_target != nullptr)
	{
		int tempwidth, tempheight;

		// see if the games video mode has changed
		m_target->compute_minimum_size(tempwidth, tempheight);
		if (osd_dim(tempwidth, tempheight) != m_minimum_dim)
		{
			m_minimum_dim = osd_dim(tempwidth, tempheight);

			if (!this->m_fullscreen)
			{
				//Don't resize window without user interaction;
				//window_resize(blitwidth, blitheight);
			}
			else if (video_config.switchres)
			{
				osd_dim tmp = this->pick_best_mode();
				resize(tmp.width(), tmp.height());
			}
		}

		if (video_config.waitvsync && video_config.syncrefresh)
			event_wait_ticks = osd_ticks_per_second(); // block at most a second
		else
			event_wait_ticks = 0;

		if (m_rendered_event.wait(event_wait_ticks))
		{
			// ensure the target bounds are up-to-date, and then get the primitives

			render_primitive_list &primlist = *renderer().get_primitives();

			// and redraw now
			auto wp = std::make_unique<worker_param>(std::static_pointer_cast<sdl_window_info>(shared_from_this()), primlist);
			execute_async(&draw_video_contents_wt, std::move(wp));
		}
	}
}
예제 #2
0
파일: window.cpp 프로젝트: fesh0r/mame-full
sdl_window_info::sdl_window_info(
		running_machine &a_machine,
		int index,
		std::shared_ptr<osd_monitor_info> a_monitor,
		const osd_window_config *config)
	: osd_window_t(*config)
	, m_next(nullptr)
	, m_startmaximized(0)
	// Following three are used by input code to defer resizes
	, m_minimum_dim(0, 0)
	, m_windowed_dim(0, 0)
	, m_rendered_event(0, 1)
	, m_target(nullptr)
	, m_extra_flags(0)
	, m_machine(a_machine)
	, m_monitor(a_monitor)
	, m_fullscreen(0)
	, m_mouse_captured(false)
	, m_mouse_hidden(false)
{
	m_index = index;

	//FIXME: these should be per_window in config-> or even better a bit set
	m_fullscreen = !video_config.windowed;
	m_prescale = video_config.prescale;

	m_windowed_dim = osd_dim(config->width, config->height);
	m_original_mode = global_alloc(SDL_DM_Wrapper);
}
예제 #3
0
bool target_manager::update_target_sizes(uint32_t screen, uint16_t width, uint16_t height, uint32_t style)
{
	if (style == TARGET_STYLE_CUSTOM) return false;

	std::vector<osd_dim>& sizes = style == TARGET_STYLE_GUEST ? m_guest_dims : m_native_dims;

	// Ensure that there's an entry to fill
	while (sizes.size() <= screen)
	{
		sizes.push_back(osd_dim(0, 0));
	}

	if (width != sizes[screen].width() || height != sizes[screen].height())
	{
		sizes[screen] = osd_dim(width, height);
		rebuild_targets(screen, style);
		return true;
	}

	return false;
}
예제 #4
0
osd_dim sdl_window_info::blit_surface_size()
{
	osd_dim window_dim = get_size();

	int newwidth, newheight;
	float xscale = 1, yscale = 1;
	INT32 target_width = window_dim.width();
	INT32 target_height = window_dim.height();

	// start with the minimum size
	m_target->compute_minimum_size(newwidth, newheight);

	// compute the appropriate visible area if we're trying to keepaspect
	if (video_config.keepaspect)
	{
		// make sure the monitor is up-to-date
		m_target->compute_visible_area(target_width, target_height, m_monitor->aspect(), m_target->orientation(), target_width, target_height);
	}

	// non-integer scaling - often gives more pleasing results in full screen
	if (!video_config.fullstretch)
	{
		// Use SwitchRes scaling
		float width = newwidth;
		float height = newheight;
		switchres_get_scale(m_target, target_width, target_height, width, height, xscale, yscale);
		newwidth = width;
		newheight = height;

		// ensure at least a scale factor of 1
		if (xscale <= 0) xscale = 1;
		if (yscale <= 0) yscale = 1;

		// apply the final scale
		newwidth *= xscale;
		newheight *= yscale;
	}
	else
	{
		newwidth = target_width;
		newheight = target_height;
	}

	//FIXME: really necessary to distinguish for yuv_modes ?
	if (m_target->zoom_to_screen()
		&& (video_config.scale_mode == VIDEO_SCALE_MODE_NONE ))
		newwidth = window_dim.width();

	return osd_dim(newwidth, newheight);
}
예제 #5
0
osd_dim sdl_window_info::get_min_bounds(int constrain)
{
	INT32 minwidth, minheight;

	//assert(GetCurrentThreadId() == window_threadid);

	// get the minimum target size
	m_target->compute_minimum_size(minwidth, minheight);

	// expand to our minimum dimensions
	if (minwidth < MIN_WINDOW_DIM)
		minwidth = MIN_WINDOW_DIM;
	if (minheight < MIN_WINDOW_DIM)
		minheight = MIN_WINDOW_DIM;

	// account for extra window stuff
	minwidth += wnd_extra_width();
	minheight += wnd_extra_height();

	// if we want it constrained, figure out which one is larger
	if (constrain)
	{
		// first constrain with no height limit
		osd_rect test1(0,0,minwidth,10000);
		test1 = constrain_to_aspect_ratio(test1, WMSZ_BOTTOMRIGHT);

		// then constrain with no width limit
		osd_rect test2(0,0,10000,minheight);
		test2 = constrain_to_aspect_ratio(test2, WMSZ_BOTTOMRIGHT);

		// pick the larger
		if (test1.width() > test2.width())
		{
			minwidth = test1.width();
			minheight = test1.height();
		}
		else
		{
			minwidth = test2.width();
			minheight = test2.height();
		}
	}

	// remove extra window stuff
	minwidth -= wnd_extra_width();
	minheight -= wnd_extra_height();

	return osd_dim(minwidth, minheight);
}
예제 #6
0
void target_manager::update_screen_count(uint32_t count)
{
	// Ensure that there's an entry to fill
	while (count > m_native_dims.size())
	{
		m_native_dims.push_back(osd_dim(0, 0));
	}

	if (count != m_screen_count)
	{
		uint32_t old_count = m_screen_count;
		m_screen_count = count;
		if (m_screen_count > old_count)
		{
			for (uint32_t screen = old_count; screen < m_screen_count; screen++)
			{
				create_target_if_nonexistent(screen, "output", false, false, TARGET_STYLE_NATIVE);
			}
		}
	}
}
예제 #7
0
osd_dim sdl_window_info::pick_best_mode()
{
	int minimum_width, minimum_height, target_width, target_height;
	int i;
	float size_score, best_score = 0.0f;
	int best_width = 0, best_height = 0;
	SDL_Rect **modes;

	// check if we already have a best mode
	modeline *mode = &this->machine().switchres.best_mode;
	if (mode->hactive)
	{
		ret = osd_dim(mode->type & MODE_ROTATED? mode->vactive : mode->hactive, mode->type & MODE_ROTATED? mode->hactive : mode->vactive);
		return ret;
	}


	// determine the minimum width/height for the selected target
	m_target->compute_minimum_size(minimum_width, minimum_height);

	// use those as the target for now
	target_width = minimum_width * MAX(1, prescale());
	target_height = minimum_height * MAX(1, prescale());

	// if we're not stretching, allow some slop on the minimum since we can handle it
	{
		minimum_width -= 4;
		minimum_height -= 4;
	}

#if 1 // defined(SDLMAME_WIN32)
	/*
	 *  We need to do this here. If SDL_ListModes is
	 * called in init_monitors, the call will crash
	 * on win32
	 */
	modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_DOUBLEBUF);
#else
	modes = window->m_monitor->modes;
#endif

	if (modes == (SDL_Rect **)0)
	{
		osd_printf_error("SDL: No modes available?!\n");
		exit(-1);
	}
	else if (modes == (SDL_Rect **)-1)  // all modes are possible
	{
		return osd_dim(m_win_config.width, m_win_config.height);
	}
	else
	{
		for (i = 0; modes[i]; ++i)
		{
			// compute initial score based on difference between target and current
			size_score = 1.0f / (1.0f + fabsf((INT32)modes[i]->w - target_width) + fabsf((INT32)modes[i]->h - target_height));

			// if the mode is too small, give a big penalty
			if (modes[i]->w < minimum_width || modes[i]->h < minimum_height)
				size_score *= 0.01f;

			// if mode is smaller than we'd like, it only scores up to 0.1
			if (modes[i]->w < target_width || modes[i]->h < target_height)
				size_score *= 0.1f;

			// if we're looking for a particular mode, that's a winner
			if (modes[i]->w == m_win_config.width && modes[i]->h == m_win_config.height)
				size_score = 2.0f;

			osd_printf_verbose("%4dx%4d -> %f\n", (int)modes[i]->w, (int)modes[i]->h, size_score);

			// best so far?
			if (size_score > best_score)
			{
				best_score = size_score;
				best_width = modes[i]->w;
				best_height = modes[i]->h;
			}

		}
	}
	return osd_dim(best_width, best_height);
}
예제 #8
0
osd_dim sdl_window_info::pick_best_mode()
{
	int minimum_width, minimum_height, target_width, target_height;
	int i;
	int num;
	float size_score, best_score = 0.0f;
	osd_dim ret(0,0);

	// check if we already have a best mode
	modeline *mode = &this->machine().switchres.best_mode;
	if (mode->hactive)
	{
		ret = osd_dim(mode->type & MODE_ROTATED? mode->vactive : mode->hactive, mode->type & MODE_ROTATED? mode->hactive : mode->vactive);
		return ret;
	}

	// determine the minimum width/height for the selected target
	m_target->compute_minimum_size(minimum_width, minimum_height);

	// use those as the target for now
	target_width = minimum_width * MAX(1, prescale());
	target_height = minimum_height * MAX(1, prescale());

	// if we're not stretching, allow some slop on the minimum since we can handle it
	{
		minimum_width -= 4;
		minimum_height -= 4;
	}

	// FIXME: this should be provided by monitor !
	num = SDL_GetNumDisplayModes(*((UINT64 *)m_monitor->oshandle()));

	if (num == 0)
	{
		osd_printf_error("SDL: No modes available?!\n");
		exit(-1);
	}
	else
	{
		for (i = 0; i < num; ++i)
		{
			SDL_DisplayMode mode;
			SDL_GetDisplayMode(*((UINT64 *)m_monitor->oshandle()), i, &mode);

			// compute initial score based on difference between target and current
			size_score = 1.0f / (1.0f + abs((INT32)mode.w - target_width) + abs((INT32)mode.h - target_height));

			// if the mode is too small, give a big penalty
			if (mode.w < minimum_width || mode.h < minimum_height)
				size_score *= 0.01f;

			// if mode is smaller than we'd like, it only scores up to 0.1
			if (mode.w < target_width || mode.h < target_height)
				size_score *= 0.1f;

			// if we're looking for a particular mode, that's a winner
			if (mode.w == m_win_config.width && mode.h == m_win_config.height)
				size_score = 2.0f;

			// refresh adds some points
			if (m_win_config.refresh)
				size_score *= 1.0f / (1.0f + abs(m_win_config.refresh - mode.refresh_rate) / 10.0f);

			osd_printf_verbose("%4dx%4d@%2d -> %f\n", (int)mode.w, (int)mode.h, (int) mode.refresh_rate, (double) size_score);

			// best so far?
			if (size_score > best_score)
			{
				best_score = size_score;
				ret = osd_dim(mode.w, mode.h);
			}

		}
	}
	return ret;
}
예제 #9
0
void sdl_window_info::update()
{
	osd_ticks_t     event_wait_ticks;
	ASSERT_MAIN_THREAD();

	// adjust the cursor state
	//sdlwindow_update_cursor_state(machine, window);

	execute_async(&update_cursor_state_wt, worker_param(this));

	// if we're visible and running and not in the middle of a resize, draw
	if (m_target != NULL)
	{
		int tempwidth, tempheight;

		// see if the games video mode has changed
		m_target->compute_minimum_size(tempwidth, tempheight);
		if (video_config.switchres && m_fullscreen && machine().options().changeres() && machine().switchres.game.changeres)
		{
			switchres_resolution_change(this);
			return;
		}
		else if (osd_dim(tempwidth, tempheight) != m_minimum_dim)
		{
			m_minimum_dim = osd_dim(tempwidth, tempheight);

			if (!this->m_fullscreen)
			{
				//Don't resize window without user interaction;
				//window_resize(blitwidth, blitheight);
			}
			else if (video_config.switchres)
			{
				osd_dim tmp = this->pick_best_mode();
				resize(tmp.width(), tmp.height());
			}
		}

		int got_lock = false;
		got_lock = osd_lock_try(m_render_lock);

		// only render if we were able to get the lock
		if (got_lock)
		{
			// don't hold the lock; we just used it to see if rendering was still happening
			osd_lock_release(m_render_lock);

			// ensure the target bounds are up-to-date, and then get the primitives

			render_primitive_list &primlist = *m_renderer->get_primitives();

			// and redraw now
			osd_event_reset(m_rendered_event);
			execute_async(&draw_video_contents_wt, worker_param(this, primlist));

			if (video_config.waitvsync && machine().video().throttled())
			{
				event_wait_ticks = osd_ticks_per_second(); // block at most a second
				osd_event_wait(m_rendered_event, event_wait_ticks);
			}
		}
	}
}
예제 #10
0
파일: window.cpp 프로젝트: fesh0r/mame-full
void sdl_window_info::update()
{
	osd_ticks_t     event_wait_ticks;

	// adjust the cursor state
	//sdlwindow_update_cursor_state(machine, window);

	update_cursor_state();

	// if we're visible and running and not in the middle of a resize, draw
	if (m_target != nullptr)
	{
		int tempwidth, tempheight;

		// see if the games video mode has changed
		m_target->compute_minimum_size(tempwidth, tempheight);
		if (osd_dim(tempwidth, tempheight) != m_minimum_dim)
		{
			m_minimum_dim = osd_dim(tempwidth, tempheight);

			if (!this->m_fullscreen)
			{
				//Don't resize window without user interaction;
				//window_resize(blitwidth, blitheight);
			}
			else if (video_config.switchres)
			{
				osd_dim tmp = this->pick_best_mode();
				resize(tmp.width(), tmp.height());
			}
		}

		if (video_config.waitvsync && video_config.syncrefresh)
			event_wait_ticks = osd_ticks_per_second(); // block at most a second
		else
			event_wait_ticks = 0;

		if (m_rendered_event.wait(event_wait_ticks))
		{
			const int update = 1;

			// ensure the target bounds are up-to-date, and then get the primitives

			render_primitive_list &primlist = *renderer().get_primitives();

			// and redraw now

			// Some configurations require events to be polled in the worker thread
			downcast< sdl_osd_interface& >(machine().osd()).process_events_buf();

			// Check whether window has vector screens

			{
				const screen_device *screen = screen_device_iterator(machine().root_device()).byindex(m_index);
				if ((screen != nullptr) && (screen->screen_type() == SCREEN_TYPE_VECTOR))
					renderer().set_flags(osd_renderer::FLAG_HAS_VECTOR_SCREEN);
				else
					renderer().clear_flags(osd_renderer::FLAG_HAS_VECTOR_SCREEN);
			}

			m_primlist = &primlist;

			// if no bitmap, just fill
			if (m_primlist == nullptr)
			{
			}
			// otherwise, render with our drawing system
			else
			{
				if( video_config.perftest )
					measure_fps(update);
				else
					renderer().draw(update);
			}

			/* all done, ready for next */
			m_rendered_event.set();
		}
	}
}
예제 #11
0
파일: window.cpp 프로젝트: fesh0r/mame-full
osd_dim sdl_window_info::get_size()
{
	int w=0; int h=0;
	SDL_GetWindowSize(platform_window(), &w, &h);
	return osd_dim(w,h);
}
예제 #12
0
파일: drawbgfx.cpp 프로젝트: p0nley/mame
int renderer_bgfx::create()
{
	// create renderer

	osd_dim wdim = window().get_size();
	m_width[window().m_index] = wdim.width();
	m_height[window().m_index] = wdim.height();
	if (window().m_index == 0)
	{
		if (!s_window_set)
		{
			s_window_set = true;
			ScreenVertex::init();
		}
		else
		{
			bgfx::shutdown();
			bgfx::PlatformData blank_pd;
			memset(&blank_pd, 0, sizeof(bgfx::PlatformData));
			bgfx::setPlatformData(blank_pd);
		}
#ifdef OSD_WINDOWS
		bgfx::winSetHwnd(window().m_hwnd);
#else
		bgfx::sdlSetWindow(window().sdl_window());
#endif
		bgfx::init();
		bgfx::reset(m_width[window().m_index], m_height[window().m_index], video_config.waitvsync ? BGFX_RESET_VSYNC : BGFX_RESET_NONE);
		// Enable debug text.
		bgfx::setDebug(BGFX_DEBUG_TEXT); //BGFX_DEBUG_STATS
		m_dimensions = osd_dim(m_width[0], m_height[0]);
	}

	m_textures = new texture_manager();
	m_targets = new target_manager(*m_textures);
	m_shaders = new shader_manager();
	m_effects = new effect_manager(*m_shaders);

	if (window().m_index != 0)
	{
#ifdef OSD_WINDOWS
		m_framebuffer = m_targets->create_target("backbuffer", window().m_hwnd, m_width[window().m_index], m_height[window().m_index]);
#else
		m_framebuffer = m_targets->create_target("backbuffer", sdlNativeWindowHandle(window().sdl_window()), m_width[window().m_index], m_height[window().m_index]);
#endif
		bgfx::touch(window().m_index);
	}

	// Create program from shaders.
	m_gui_effect[0] = m_effects->effect("gui_opaque");
	m_gui_effect[1] = m_effects->effect("gui_blend");
	m_gui_effect[2] = m_effects->effect("gui_multiply");
	m_gui_effect[3] = m_effects->effect("gui_add");

	m_screen_effect[0] = m_effects->effect("screen_opaque");
	m_screen_effect[1] = m_effects->effect("screen_blend");
	m_screen_effect[2] = m_effects->effect("screen_multiply");
	m_screen_effect[3] = m_effects->effect("screen_add");

	uint32_t flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP | BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT | BGFX_TEXTURE_MIP_POINT;
	m_texture_cache = m_textures->create_texture("#cache", bgfx::TextureFormat::RGBA8, CACHE_SIZE, CACHE_SIZE, nullptr, flags);

	memset(m_white, 0xff, sizeof(uint32_t) * 16 * 16);
	m_texinfo.push_back(rectangle_packer::packable_rectangle(WHITE_HASH, PRIMFLAG_TEXFORMAT(TEXFORMAT_ARGB32), 16, 16, 16, nullptr, m_white));

	return 0;
}
예제 #13
0
파일: window.c 프로젝트: mbcoguno/mame
osd_dim sdl_window_info::blit_surface_size()
{
	osd_dim window_dim = get_size();

	int newwidth, newheight;
	int xscale = 1, yscale = 1;
	float desired_aspect = 1.0f;
	INT32 target_width = window_dim.width();
	INT32 target_height = window_dim.height();

	// start with the minimum size
	m_target->compute_minimum_size(newwidth, newheight);

	// compute the appropriate visible area if we're trying to keepaspect
	if (video_config.keepaspect)
	{
		// make sure the monitor is up-to-date
		m_target->compute_visible_area(target_width, target_height, m_monitor->aspect(), m_target->orientation(), target_width, target_height);
		desired_aspect = (float)target_width / (float)target_height;
	}

	// non-integer scaling - often gives more pleasing results in full screen
	if (!video_config.fullstretch)
	{
		// compute maximum integral scaling to fit the window
		xscale = (target_width + 2) / newwidth;
		yscale = (target_height + 2) / newheight;

		// try a little harder to keep the aspect ratio if desired
		if (video_config.keepaspect)
		{
			// if we could stretch more in the X direction, and that makes a better fit, bump the xscale
			while (newwidth * (xscale + 1) <= window_dim.width() &&
				better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale + 1), newheight * yscale, desired_aspect))
				xscale++;

			// if we could stretch more in the Y direction, and that makes a better fit, bump the yscale
			while (newheight * (yscale + 1) <= window_dim.height() &&
				better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale + 1), desired_aspect))
				yscale++;

			// now that we've maxed out, see if backing off the maximally stretched one makes a better fit
			if (window_dim.width() - newwidth * xscale < window_dim.height() - newheight * yscale)
			{
				while (better_mode(newwidth * xscale, newheight * yscale, newwidth * (xscale - 1), newheight * yscale, desired_aspect) && (xscale >= 0))
					xscale--;
			}
			else
			{
				while (better_mode(newwidth * xscale, newheight * yscale, newwidth * xscale, newheight * (yscale - 1), desired_aspect) && (yscale >= 0))
					yscale--;
			}
		}

		// ensure at least a scale factor of 1
		if (xscale <= 0) xscale = 1;
		if (yscale <= 0) yscale = 1;

		// apply the final scale
		newwidth *= xscale;
		newheight *= yscale;
	}
	else
	{
		newwidth = target_width;
		newheight = target_height;
	}

	//FIXME: really necessary to distinguish for yuv_modes ?
	if (m_target->zoom_to_screen()
		&& (video_config.scale_mode == VIDEO_SCALE_MODE_NONE ))
		newwidth = window_dim.width();

	return osd_dim(newwidth, newheight);
}