예제 #1
0
파일: drawdd.cpp 프로젝트: waisam/mame
void renderer_dd::ddraw_delete()
{
	// free surfaces
	ddraw_delete_surfaces();

	// restore resolutions
	if (ddraw != NULL)
		IDirectDraw7_RestoreDisplayMode(ddraw);

	// reset cooperative level
	if (ddraw != NULL && window().m_hwnd != NULL)
		IDirectDraw7_SetCooperativeLevel(ddraw, window().m_hwnd, DDSCL_NORMAL);

	// release the DirectDraw object itself
	if (ddraw != NULL)
		IDirectDraw7_Release(ddraw);
	ddraw = NULL;
}
예제 #2
0
static void ddraw_delete(win_window_info *window)
{
	dd_info *dd = window->drawdata;

	// free surfaces
	ddraw_delete_surfaces(window);

	// restore resolutions
	if (dd->ddraw != NULL)
		IDirectDraw7_RestoreDisplayMode(dd->ddraw);

	// reset cooperative level
	if (dd->ddraw != NULL && window->hwnd != NULL)
		IDirectDraw7_SetCooperativeLevel(dd->ddraw, window->hwnd, DDSCL_NORMAL);

	// release the DirectDraw object itself
	if (dd->ddraw != NULL)
		IDirectDraw7_Release(dd->ddraw);
	dd->ddraw = NULL;
}
예제 #3
0
파일: drawdd.cpp 프로젝트: waisam/mame
int renderer_dd::ddraw_test_cooperative()
{
	HRESULT result;

	// check our current status; if we lost the device, punt to GDI
	result = IDirectDraw7_TestCooperativeLevel(ddraw);
	switch (result)
	{
		// punt to GDI if someone else has exclusive mode
		case DDERR_NOEXCLUSIVEMODE:
		case DDERR_EXCLUSIVEMODEALREADYSET:
			ddraw_delete_surfaces();
			return 1;

		// if we're ok, but we don't have a primary surface, create one
		default:
		case DD_OK:
			if (primary == NULL)
				return ddraw_create_surfaces();
			return 0;
	}
}
예제 #4
0
static int ddraw_test_cooperative(win_window_info *window)
{
	dd_info *dd = (dd_info *)window->drawdata;
	HRESULT result;

	// check our current status; if we lost the device, punt to GDI
	result = IDirectDraw7_TestCooperativeLevel(dd->ddraw);
	switch (result)
	{
		// punt to GDI if someone else has exclusive mode
		case DDERR_NOEXCLUSIVEMODE:
		case DDERR_EXCLUSIVEMODEALREADYSET:
			ddraw_delete_surfaces(window);
			return 1;

		// if we're ok, but we don't have a primary surface, create one
		default:
		case DD_OK:
			if (dd->primary == NULL)
				return ddraw_create_surfaces(window);
			return 0;
	}
}
예제 #5
0
static int ddraw_create_surfaces(win_window_info *window)
{
	dd_info *dd = window->drawdata;
	HRESULT result;

	// make a description of the primary surface
	memset(&dd->primarydesc, 0, sizeof(dd->primarydesc));
	dd->primarydesc.dwSize = sizeof(dd->primarydesc);
	dd->primarydesc.dwFlags = DDSD_CAPS;
	dd->primarydesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

	// for triple-buffered full screen mode, allocate flipping surfaces
	if (window->fullscreen && video_config.triplebuf)
	{
		dd->primarydesc.dwFlags |= DDSD_BACKBUFFERCOUNT;
		dd->primarydesc.ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX;
		dd->primarydesc.dwBackBufferCount = 2;
	}

	// create the primary surface and report errors
	result = create_surface(dd, &dd->primarydesc, &dd->primary, "primary");
	if (result != DD_OK) goto error;

	// full screen mode: get the back surface
	dd->back = NULL;
	if (window->fullscreen && video_config.triplebuf)
	{
		DDSCAPS2 caps = { DDSCAPS_BACKBUFFER };
		result = IDirectDrawSurface7_GetAttachedSurface(dd->primary, &caps, &dd->back);
		if (result != DD_OK)
		{
			mame_printf_verbose("DirectDraw: Error %08X getting attached back surface\n", (int)result);
			goto error;
		}
	}

	// now make a description of our blit surface, based on the primary surface
	if (dd->blitwidth == 0 || dd->blitheight == 0)
		compute_blit_surface_size(window);
	dd->blitdesc = dd->primarydesc;
	dd->blitdesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
	dd->blitdesc.dwWidth = dd->blitwidth;
	dd->blitdesc.dwHeight = dd->blitheight;
	dd->blitdesc.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;

	// then create the blit surface, fall back to system memory if video mem doesn't work
	result = create_surface(dd, &dd->blitdesc, &dd->blit, "blit");
	if (result != DD_OK)
	{
		dd->blitdesc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
		result = create_surface(dd, &dd->blitdesc, &dd->blit, "blit");
	}
	if (result != DD_OK) goto error;

	// create a memory buffer for offscreen drawing
	if (dd->membuffersize < dd->blitwidth * dd->blitheight * 4)
	{
		dd->membuffersize = dd->blitwidth * dd->blitheight * 4;
		dd->membuffer = realloc(dd->membuffer, dd->membuffersize);
	}
	if (dd->membuffer == NULL)
		goto error;

#ifdef MESS
	// create a clipper for all modes, since MESS has dialogs
	if (create_clipper(window))
		goto error;
#else
	// create a clipper for windowed mode
	if (!window->fullscreen && create_clipper(window))
		goto error;
#endif

	// full screen mode: set the gamma
	if (window->fullscreen)
	{
		// only set the gamma if it's not 1.0f
		float brightness = options_get_float(mame_options(), WINOPTION_FULLSCREENBRIGHTNESS);
		float contrast = options_get_float(mame_options(), WINOPTION_FULLLSCREENCONTRAST);
		float gamma = options_get_float(mame_options(), WINOPTION_FULLSCREENGAMMA);
		if (brightness != 1.0f || contrast != 1.0f || gamma != 1.0f)
		{
			// see if we can get a GammaControl object
			result = IDirectDrawSurface_QueryInterface(dd->primary, &IID_IDirectDrawGammaControl, (void **)&dd->gamma);
			if (result != DD_OK)
			{
				mame_printf_warning("DirectDraw: Warning - device does not support full screen gamma correction.\n");
				dd->gamma = NULL;
			}

			// proceed if we can
			if (dd->gamma != NULL)
			{
				DDGAMMARAMP ramp;
				int i;

				// create a standard ramp and set it
				for (i = 0; i < 256; i++)
					ramp.red[i] = ramp.green[i] = ramp.blue[i] = apply_brightness_contrast_gamma(i, brightness, contrast, gamma) << 8;

				// attempt to set it
				result = IDirectDrawGammaControl_SetGammaRamp(dd->gamma, 0, &ramp);
				if (result != DD_OK)
					mame_printf_verbose("DirectDraw: Error %08X attempting to set gamma correction.\n", (int)result);
			}
		}
	}

	// force some updates
	update_outer_rects(dd);
	return 0;

error:
	ddraw_delete_surfaces(window);
	return 1;
}
예제 #6
0
static int drawdd_window_draw(win_window_info *window, HDC dc, int update)
{
	dd_info *dd = window->drawdata;
	const render_primitive *prim;
	int usemembuffer = FALSE;
	HRESULT result;

	// if we haven't been created, just punt
	if (dd == NULL)
		return 1;

	// if we're updating, remember to erase the outer stuff
	if (update)
		update_outer_rects(dd);

	// if we have a ddraw object, check the cooperative level
	if (ddraw_test_cooperative(window))
		return 1;

	// get the size; if we're too small, delete the existing surfaces
	if (dd->blitwidth > dd->blitdesc.dwWidth || dd->blitheight > dd->blitdesc.dwHeight)
		ddraw_delete_surfaces(window);

	// if we need to create surfaces, do it now
	if (dd->blit == NULL && ddraw_create_surfaces(window) != 0)
		return 1;

	// select our surface and lock it
	result = IDirectDrawSurface7_Lock(dd->blit, NULL, &dd->blitdesc, DDLOCK_WAIT, NULL);
	if (result == DDERR_SURFACELOST)
	{
		mame_printf_verbose("DirectDraw: Lost surfaces; deleting and retrying next frame\n");
		ddraw_delete_surfaces(window);
		return 1;
	}
	if (result != DD_OK)
	{
		mame_printf_verbose("DirectDraw: Error %08X locking blit surface\n", (int)result);
		return 1;
	}

	// render to it
	osd_lock_acquire(window->primlist->lock);

	// scan the list of primitives for tricky stuff
	for (prim = window->primlist->head; prim != NULL; prim = prim->next)
		if (PRIMFLAG_GET_BLENDMODE(prim->flags) != BLENDMODE_NONE ||
			(prim->texture.base != NULL && PRIMFLAG_GET_TEXFORMAT(prim->flags) == TEXFORMAT_ARGB32))
		{
			usemembuffer = TRUE;
			break;
		}

	// if we're using the memory buffer, draw offscreen first and then copy
	if (usemembuffer)
	{
		int x, y;

		// based on the target format, use one of our standard renderers
		switch (dd->blitdesc.ddpfPixelFormat.dwRBitMask)
		{
			case 0x00ff0000: 	drawdd_rgb888_draw_primitives(window->primlist->head, dd->membuffer, dd->blitwidth, dd->blitheight, dd->blitwidth);	break;
			case 0x000000ff:	drawdd_bgr888_draw_primitives(window->primlist->head, dd->membuffer, dd->blitwidth, dd->blitheight, dd->blitwidth);	break;
			case 0xf800:		drawdd_rgb565_draw_primitives(window->primlist->head, dd->membuffer, dd->blitwidth, dd->blitheight, dd->blitwidth);	break;
			case 0x7c00:		drawdd_rgb555_draw_primitives(window->primlist->head, dd->membuffer, dd->blitwidth, dd->blitheight, dd->blitwidth);	break;
			default:
				mame_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)dd->blitdesc.ddpfPixelFormat.dwRBitMask, (int)dd->blitdesc.ddpfPixelFormat.dwGBitMask, (int)dd->blitdesc.ddpfPixelFormat.dwBBitMask);
				break;
		}

		// handle copying to both 16bpp and 32bpp destinations
		for (y = 0; y < dd->blitheight; y++)
		{
			if (dd->blitdesc.ddpfPixelFormat.dwRGBBitCount == 32)
			{
				UINT32 *src = (UINT32 *)dd->membuffer + y * dd->blitwidth;
				UINT32 *dst = (UINT32 *)((UINT8 *)dd->blitdesc.lpSurface + y * dd->blitdesc.lPitch);
				for (x = 0; x < dd->blitwidth; x++)
					*dst++ = *src++;
			}
			else if (dd->blitdesc.ddpfPixelFormat.dwRGBBitCount == 16)
			{
				UINT16 *src = (UINT16 *)dd->membuffer + y * dd->blitwidth;
				UINT16 *dst = (UINT16 *)((UINT8 *)dd->blitdesc.lpSurface + y * dd->blitdesc.lPitch);
				for (x = 0; x < dd->blitwidth; x++)
					*dst++ = *src++;
			}
		}

	}

	// otherwise, draw directly
	else
	{
		// based on the target format, use one of our standard renderers
		switch (dd->blitdesc.ddpfPixelFormat.dwRBitMask)
		{
			case 0x00ff0000: 	drawdd_rgb888_nr_draw_primitives(window->primlist->head, dd->blitdesc.lpSurface, dd->blitwidth, dd->blitheight, dd->blitdesc.lPitch / 4);	break;
			case 0x000000ff:	drawdd_bgr888_nr_draw_primitives(window->primlist->head, dd->blitdesc.lpSurface, dd->blitwidth, dd->blitheight, dd->blitdesc.lPitch / 4);	break;
			case 0xf800:		drawdd_rgb565_nr_draw_primitives(window->primlist->head, dd->blitdesc.lpSurface, dd->blitwidth, dd->blitheight, dd->blitdesc.lPitch / 2);	break;
			case 0x7c00:		drawdd_rgb555_nr_draw_primitives(window->primlist->head, dd->blitdesc.lpSurface, dd->blitwidth, dd->blitheight, dd->blitdesc.lPitch / 2);	break;
			default:
				mame_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)dd->blitdesc.ddpfPixelFormat.dwRBitMask, (int)dd->blitdesc.ddpfPixelFormat.dwGBitMask, (int)dd->blitdesc.ddpfPixelFormat.dwBBitMask);
				break;
		}
	}
	osd_lock_release(window->primlist->lock);

	// unlock and blit
	result = IDirectDrawSurface7_Unlock(dd->blit, NULL);
	if (result != DD_OK) mame_printf_verbose("DirectDraw: Error %08X unlocking blit surface\n", (int)result);

	// sync to VBLANK
	if ((video_config.waitvsync || video_config.syncrefresh) && video_get_throttle() && (!window->fullscreen || dd->back == NULL))
	{
		result = IDirectDraw7_WaitForVerticalBlank(dd->ddraw, DDWAITVB_BLOCKBEGIN, NULL);
		if (result != DD_OK) mame_printf_verbose("DirectDraw: Error %08X waiting for VBLANK\n", (int)result);
	}

	// complete the blitting
	blit_to_primary(window, dd->blitwidth, dd->blitheight);
	return 0;
}
예제 #7
0
파일: drawdd.cpp 프로젝트: waisam/mame
int renderer_dd::ddraw_create_surfaces()
{
	HRESULT result;

	// make a description of the primary surface
	memset(&primarydesc, 0, sizeof(primarydesc));
	primarydesc.dwSize = sizeof(primarydesc);
	primarydesc.dwFlags = DDSD_CAPS;
	primarydesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

	// for triple-buffered full screen mode, allocate flipping surfaces
	if (window().fullscreen() && video_config.triplebuf)
	{
		primarydesc.dwFlags |= DDSD_BACKBUFFERCOUNT;
		primarydesc.ddsCaps.dwCaps |= DDSCAPS_FLIP | DDSCAPS_COMPLEX;
		primarydesc.dwBackBufferCount = 2;
	}

	// create the primary surface and report errors
	result = create_surface(&primarydesc, &primary, "primary");
	if (result != DD_OK) goto error;

	// full screen mode: get the back surface
	back = NULL;
	if (window().fullscreen() && video_config.triplebuf)
	{
		DDSCAPS2 caps = { DDSCAPS_BACKBUFFER };
		result = IDirectDrawSurface7_GetAttachedSurface(primary, &caps, &back);
		if (result != DD_OK)
		{
			osd_printf_verbose("DirectDraw: Error %08X getting attached back surface\n", (int)result);
			goto error;
		}
	}

	// now make a description of our blit surface, based on the primary surface
	if (blitwidth == 0 || blitheight == 0)
		compute_blit_surface_size();
	blitdesc = primarydesc;
	blitdesc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
	blitdesc.dwWidth = blitwidth;
	blitdesc.dwHeight = blitheight;
	blitdesc.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;

	// then create the blit surface, fall back to system memory if video mem doesn't work
	result = create_surface(&blitdesc, &blit, "blit");
	if (result != DD_OK)
	{
		blitdesc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY;
		result = create_surface(&blitdesc, &blit, "blit");
	}
	if (result != DD_OK) goto error;

	// create a memory buffer for offscreen drawing
	if (membuffersize < blitwidth * blitheight * 4)
	{
		membuffersize = blitwidth * blitheight * 4;
		global_free_array(membuffer);
		membuffer = global_alloc_array_nothrow(UINT8, membuffersize);
	}
	if (membuffer == NULL)
		goto error;

	// create a clipper for windowed mode
	if (!window().fullscreen() && create_clipper())
		goto error;

	// full screen mode: set the gamma
	if (window().fullscreen())
	{
		// only set the gamma if it's not 1.0f
		windows_options &options = downcast<windows_options &>(window().machine().options());
		float brightness = options.full_screen_brightness();
		float contrast = options.full_screen_contrast();
		float fgamma = options.full_screen_gamma();
		if (brightness != 1.0f || contrast != 1.0f || fgamma != 1.0f)
		{
			// see if we can get a GammaControl object
			result = IDirectDrawSurface_QueryInterface(primary, WRAP_REFIID(IID_IDirectDrawGammaControl), (void **)&gamma);
			if (result != DD_OK)
			{
				osd_printf_warning("DirectDraw: Warning - device does not support full screen gamma correction.\n");
				this->gamma = NULL;
			}

			// proceed if we can
			if (this->gamma != NULL)
			{
				DDGAMMARAMP ramp;
				int i;

				// create a standard ramp and set it
				for (i = 0; i < 256; i++)
					ramp.red[i] = ramp.green[i] = ramp.blue[i] = apply_brightness_contrast_gamma(i, brightness, contrast, fgamma) << 8;

				// attempt to set it
				result = IDirectDrawGammaControl_SetGammaRamp(this->gamma, 0, &ramp);
				if (result != DD_OK)
					osd_printf_verbose("DirectDraw: Error %08X attempting to set gamma correction.\n", (int)result);
			}
		}
	}

	// force some updates
	update_outer_rects();
	return 0;

error:
	ddraw_delete_surfaces();
	return 1;
}
예제 #8
0
파일: drawdd.cpp 프로젝트: waisam/mame
int renderer_dd::draw(const int update)
{
	render_primitive *prim;
	int usemembuffer = FALSE;
	HRESULT result;

	// if we're updating, remember to erase the outer stuff
	if (update)
		update_outer_rects();

	// if we have a ddraw object, check the cooperative level
	if (ddraw_test_cooperative())
		return 1;

	// get the size; if we're too small, delete the existing surfaces
	if (blitwidth > blitdesc.dwWidth || blitheight > blitdesc.dwHeight)
		ddraw_delete_surfaces();

	// if we need to create surfaces, do it now
	if (blit == NULL && ddraw_create_surfaces() != 0)
		return 1;

	// select our surface and lock it
	result = IDirectDrawSurface7_Lock(blit, NULL, &blitdesc, DDLOCK_WAIT, NULL);
	if (result == DDERR_SURFACELOST)
	{
		osd_printf_verbose("DirectDraw: Lost surfaces; deleting and retrying next frame\n");
		ddraw_delete_surfaces();
		return 1;
	}
	if (result != DD_OK)
	{
		osd_printf_verbose("DirectDraw: Error %08X locking blit surface\n", (int)result);
		return 1;
	}

	// render to it
	window().m_primlist->acquire_lock();

	// scan the list of primitives for tricky stuff
	for (prim = window().m_primlist->first(); prim != NULL; prim = prim->next())
		if (PRIMFLAG_GET_BLENDMODE(prim->flags) != BLENDMODE_NONE ||
			(prim->texture.base != NULL && PRIMFLAG_GET_TEXFORMAT(prim->flags) == TEXFORMAT_ARGB32))
		{
			usemembuffer = TRUE;
			break;
		}

	// if we're using the memory buffer, draw offscreen first and then copy
	if (usemembuffer)
	{
		int x, y;

		// based on the target format, use one of our standard renderers
		switch (blitdesc.ddpfPixelFormat.dwRBitMask)
		{
			case 0x00ff0000:    software_renderer<UINT32, 0,0,0, 16,8,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth);  break;
			case 0x000000ff:    software_renderer<UINT32, 0,0,0, 0,8,16>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth);  break;
			case 0xf800:        software_renderer<UINT16, 3,2,3, 11,5,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth);  break;
			case 0x7c00:        software_renderer<UINT16, 3,3,3, 10,5,0>::draw_primitives(*window().m_primlist, membuffer, blitwidth, blitheight, blitwidth);  break;
			default:
				osd_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)blitdesc.ddpfPixelFormat.dwRBitMask, (int)blitdesc.ddpfPixelFormat.dwGBitMask, (int)blitdesc.ddpfPixelFormat.dwBBitMask);
				break;
		}

		// handle copying to both 16bpp and 32bpp destinations
		for (y = 0; y < blitheight; y++)
		{
			if (blitdesc.ddpfPixelFormat.dwRGBBitCount == 32)
			{
				UINT32 *src = (UINT32 *)membuffer + y * blitwidth;
				UINT32 *dst = (UINT32 *)((UINT8 *)blitdesc.lpSurface + y * blitdesc.lPitch);
				for (x = 0; x < blitwidth; x++)
					*dst++ = *src++;
			}
			else if (blitdesc.ddpfPixelFormat.dwRGBBitCount == 16)
			{
				UINT16 *src = (UINT16 *)membuffer + y * blitwidth;
				UINT16 *dst = (UINT16 *)((UINT8 *)blitdesc.lpSurface + y * blitdesc.lPitch);
				for (x = 0; x < blitwidth; x++)
					*dst++ = *src++;
			}
		}

	}

	// otherwise, draw directly
	else
	{
		// based on the target format, use one of our standard renderers
		switch (blitdesc.ddpfPixelFormat.dwRBitMask)
		{
			case 0x00ff0000:    software_renderer<UINT32, 0,0,0, 16,8,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 4); break;
			case 0x000000ff:    software_renderer<UINT32, 0,0,0, 0,8,16, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 4); break;
			case 0xf800:        software_renderer<UINT16, 3,2,3, 11,5,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 2); break;
			case 0x7c00:        software_renderer<UINT16, 3,3,3, 10,5,0, true>::draw_primitives(*window().m_primlist, blitdesc.lpSurface, blitwidth, blitheight, blitdesc.lPitch / 2); break;
			default:
				osd_printf_verbose("DirectDraw: Unknown target mode: R=%08X G=%08X B=%08X\n", (int)blitdesc.ddpfPixelFormat.dwRBitMask, (int)blitdesc.ddpfPixelFormat.dwGBitMask, (int)blitdesc.ddpfPixelFormat.dwBBitMask);
				break;
		}
	}
	window().m_primlist->release_lock();

	// unlock and blit
	result = IDirectDrawSurface7_Unlock(blit, NULL);
	if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X unlocking blit surface\n", (int)result);

	// sync to VBLANK
	if ((video_config.waitvsync || video_config.syncrefresh) && window().machine().video().throttled() && (!window().fullscreen() || back == NULL))
	{
		result = IDirectDraw7_WaitForVerticalBlank(ddraw, DDWAITVB_BLOCKBEGIN, NULL);
		if (result != DD_OK) osd_printf_verbose("DirectDraw: Error %08X waiting for VBLANK\n", (int)result);
	}

	// complete the blitting
	blit_to_primary(blitwidth, blitheight);
	return 0;
}