Exemplo n.º 1
0
static M4Err DD_FlushVideo(VideoOutput *dr, M4Window *dest)
{
	RECT rc;
	HRESULT hr;
	DDCONTEXT;

	if (!dd) return M4BadParam;
	if (dd->is_3D_out) {
		SwapBuffers(dd->gl_HDC);
		return M4OK;
	}
	if (!dd->ddraw_init) return M4BadParam;

	if (dest) {
		POINT pt;
		pt.x = dest->x;
		pt.y = dest->y;
		ClientToScreen(dd->hWnd, &pt);
		dest->x = pt.x;
		dest->y = pt.y;
		MAKERECT(rc, dest);
		hr = IDirectDrawSurface_Blt(dd->pPrimary, &rc, dd->pBack, NULL, DDBLT_WAIT, NULL );
	} else {
		hr = IDirectDrawSurface_Blt(dd->pPrimary, NULL, dd->pBack, NULL, DDBLT_WAIT, NULL );
	}
	if (hr == DDERR_SURFACELOST) {
		IDirectDrawSurface_Restore(dd->pPrimary);
		IDirectDrawSurface_Restore(dd->pBack);
	}
	return FAILED(hr) ? M4IOErr : M4OK;
}
Exemplo n.º 2
0
static boolean BltCopy( LPDIRECTDRAWSURFACE src_surface, RECT * src_rect,
		 LPDIRECTDRAWSURFACE dst_surface, RECT * dst_rect )
{
  DDSURFACEDESC	ddsd_target;
  HRESULT	result;

  memset( &ddsd_target, 0, sizeof( ddsd_target ) );
  ddsd_target.dwSize = sizeof( ddsd_target );

  /* attempt to blt the surface sontents */

  result = IDirectDrawSurface_Blt( dst_surface, dst_rect, src_surface, src_rect, DDBLT_WAIT, 0 );
  if( result != DD_OK )
    {
      if( result != DDERR_SURFACELOST )
	{
	  IDirectDrawSurface_Restore( src_surface );
	  IDirectDrawSurface_Restore( dst_surface );

	  IDirectDrawSurface_Blt( dst_surface, dst_rect, src_surface, src_rect, DDBLT_WAIT, 0 );
	}
      else
	{
	  Error( 0, "IDirectDrawSurface_Blt : error 0x%lx", result );
	  return FALSE;
	}
    }

  return TRUE;
}
Exemplo n.º 3
0
static boolean Overlay( LPDIRECTDRAWSURFACE src_surface, RECT * src_rect,
		 LPDIRECTDRAWSURFACE dst_surface, RECT * dst_rect,
		 COLORREF color_key )
{
  DWORD			dw_color_key;
  DDPIXELFORMAT		ddpf;
  DDOVERLAYFX		ddofx;
  int			flags;
  HRESULT		result;

  /* compute the colorkey pixel value from the RGB value we've got/
   * NOTE : based on videolan colorkey code */

  memset( &ddpf, 0, sizeof( DDPIXELFORMAT ));
  ddpf.dwSize = sizeof( DDPIXELFORMAT );
  result = IDirectDrawSurface_GetPixelFormat( dst_surface, &ddpf );
  if( result != DD_OK )
    {
      Error( 0, "IDirectDrawSurface_GetPixelFormat : could not get surface pixel format" );
      return FALSE;
    }

  dw_color_key = ( DWORD ) color_key;
  dw_color_key = ( DWORD ) ( ( ( dw_color_key * ddpf.dwRBitMask ) / 255 ) & ddpf.dwRBitMask );

  memset( &ddofx, 0, sizeof( DDOVERLAYFX ) );
  ddofx.dwSize = sizeof( DDOVERLAYFX );
  ddofx.dckDestColorkey.dwColorSpaceLowValue = dw_color_key;
  ddofx.dckDestColorkey.dwColorSpaceHighValue = dw_color_key;

  /* set our overlay flags */

  flags = DDOVER_SHOW | DDOVER_KEYDESTOVERRIDE;

  /* attempt to overlay the surface */

  result = IDirectDrawSurface_UpdateOverlay( src_surface, src_rect, dst_surface, dst_rect, flags, &ddofx );
  if( result != DD_OK )
    {
      if( result == DDERR_SURFACELOST )
	{
	  IDirectDrawSurface_Restore( src_surface );
	  IDirectDrawSurface_Restore( dst_surface );

	  IDirectDrawSurface_UpdateOverlay( src_surface, src_rect, dst_surface, dst_rect, flags, &ddofx );
	}
      else
	{
	  Error( 0, "IDirectDrawSurface_UpdateOverlay : error 0x%lx. You can try disable hardware acceleration (option video.directx.hwaccel).", result );
	  return FALSE;
	}
    }

  return TRUE;
}
Exemplo n.º 4
0
/* Display buffer */
static void PaintDD()
{
    DWORD ddrval;
    if (!IsWindowVisible(hWnd) || !active || !initialized
	|| !BackSurface[0])
	return;
    IDirectDrawSurface_Unlock(BackSurface[0], surface[0].lpSurface);
    IDirectDrawSurface_Unlock(BackSurface[1], surface[1].lpSurface);
    if (directX == DXFULLSCREEN) {
	if (storeddata)
	    free(storeddata), storeddata = NULL;
	storeddata =
	    store(currentbuff ? buffer2 : buffer1, bitDepth, lineSize,
		  displayX, displayY, mouseX, mouseY);
	drawmouse(currentbuff ? buffer2 : buffer1, mousepointer, bitDepth,
		  lineSize, displayX, displayY, mouseX, mouseY);
	ddrval =
	    IDirectDrawSurface_BltFast(lpSurfaces[0], 0, 0,
				       BackSurface[currentbuff], &rcScreen,
				       FALSE);
	restore(currentbuff ? buffer2 : buffer1, storeddata, bitDepth,
		lineSize, displayX, displayY, mouseX, mouseY);
	oldmouseX = mouseX;
	oldmouseY = mouseY;
    } else {
	ddrval = IDirectDrawSurface_Blt(lpSurfaces[0], &rcScreen,
					BackSurface[currentbuff],
					&rcViewport, DDBLT_WAIT, NULL);
    }
    if (ddrval != DD_OK) {
	if ((int) ddrval == (int) DDERR_SURFACELOST) {
	    IDirectDrawSurface_Restore(lpSurfaces[0]);
	    IDirectDrawSurface_Restore(BackSurface[0]);
	    IDirectDrawSurface_Restore(BackSurface[1]);
	    ddrval = IDirectDrawSurface_Blt(lpSurfaces[0], &rcScreen,
					    BackSurface[currentbuff],
					    &rcViewport, DDBLT_WAIT, NULL);
	    //if (ddrval == DDERR_SURFACELOST) resized=1; /*We've lost our fractal*/
	}
    }
    ddrval = IDirectDrawSurface_Lock(BackSurface[0], NULL, &surface[0],
				     DDLOCK_WAIT, NULL);
    ddrval = IDirectDrawSurface_Lock(BackSurface[1], NULL, &surface[1],
				     DDLOCK_WAIT, NULL);
    if (buffer1 != (char *) surface[0].lpSurface ||
	buffer2 != (char *) surface[1].lpSurface) {
	DeInitDD();
	x_fatalerror
	    ("Unexpected event - buffers moved! Please contact authors!");
    }
    needredraw = 0;

}
Exemplo n.º 5
0
//
// Flip the real page with virtual page
// - in bAppFullScreen mode, do page flipping
// - in windowed mode, copy the hidden surface to the visible surface
//
// waitflip : if not 0, wait for page flip to end
BOOL ScreenFlip(int waitflip)
{
	HRESULT hr;
	RECT rect;

	UNREFERENCED_PARAMETER(waitflip);
	if (bAppFullScreen)
	{
		//hr = IDirectDrawSurface_GetFlipStatus (ScreenReal, DDGFS_);

		// In full-screen exclusive mode, do a hardware flip.
		hr = IDirectDrawSurface_Flip(ScreenReal, NULL, DDFLIP_WAIT);   //return immediately

		// If the surface was lost, restore it.
		if (hr == DDERR_SURFACELOST)
		{
			IDirectDrawSurface_Restore(ScreenReal);

			// The restore worked, so try the flip again.
			hr = IDirectDrawSurface_Flip(ScreenReal, 0, DDFLIP_WAIT);
		}
	}
	else
	{
		rect.left = windowPosX;
		rect.top = windowPosY;
		rect.right = windowPosX + ScreenWidth - 1;
		rect.bottom = windowPosY + ScreenHeight - 1;

		// Copy the back buffer to front.
		hr = IDirectDrawSurface_Blt(ScreenReal, &rect, ScreenVirtual, 0, DDBLT_WAIT, 0);

		if (hr != DD_OK)
		{
			// If the surfaces were lost, restore them.
			if (IDirectDrawSurface_IsLost(ScreenReal) == DDERR_SURFACELOST)
				IDirectDrawSurface_Restore(ScreenReal);

			if (IDirectDrawSurface_IsLost(ScreenVirtual) == DDERR_SURFACELOST)
				IDirectDrawSurface_Restore(ScreenVirtual);

			// Retry the copy.
			hr = IDirectDrawSurface_Blt(ScreenReal,&rect, ScreenVirtual, 0, DDBLT_WAIT, 0);
		}
	}

	if (hr != DD_OK)
		I_Error("ScreenFlip() : couldn't Flip surfaces because %s", DXErrorToString(hr));

	return FALSE;
}
Exemplo n.º 6
0
static void testsurface(void)
{
    const char* testMsg = "ddraw device context test";
    HDC hdc;
    HRESULT rc;
    
    rc = IDirectDrawSurface_GetDC(lpDDSBack, &hdc);
    ok(rc==DD_OK, "IDirectDrawSurface_GetDC returned: %x\n",rc);
    SetBkColor(hdc, RGB(0, 0, 255));
    SetTextColor(hdc, RGB(255, 255, 0));
    TextOut(hdc, 0, 0, testMsg, lstrlen(testMsg));
    IDirectDrawSurface_ReleaseDC(lpDDSBack, hdc);
    ok(rc==DD_OK, "IDirectDrawSurface_ReleaseDC returned: %x\n",rc);
    
    while (1)
    {
        rc = IDirectDrawSurface_Flip(lpDDSPrimary, NULL, DDFLIP_WAIT);
        ok(rc==DD_OK || rc==DDERR_SURFACELOST, "IDirectDrawSurface_BltFast returned: %x\n",rc);

        if (rc == DD_OK)
        {
            break;
        }
        else if (rc == DDERR_SURFACELOST)
        {
            rc = IDirectDrawSurface_Restore(lpDDSPrimary);
            ok(rc==DD_OK, "IDirectDrawSurface_Restore returned: %x\n",rc);
        }
    }
}
Exemplo n.º 7
0
//
// CreateNewSurface
//
static inline IDirectDrawSurface* CreateNewSurface(int dwWidth,
                                                   int dwHeight,
                                                   int dwSurfaceCaps)
{
	DDSURFACEDESC       ddsd;
	HRESULT             hr;
	LPDIRECTDRAWSURFACE psurf;

	ZeroMemory(&ddsd, sizeof (ddsd));
	ddsd.dwSize = sizeof (ddsd);
	ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;

	ddsd.ddsCaps.dwCaps = dwSurfaceCaps;

	ddsd.dwHeight = dwHeight;
	ddsd.dwWidth = dwWidth;

	hr = IDirectDraw2_CreateSurface (DDr2, &ddsd, &psurf, NULL);

	if (hr == DD_OK)
	{
		//DDCOLORKEY ddck;
		IDirectDrawSurface_Restore(psurf);

		//hr = IDirectDrawSurface_GetColorKey(DDCKEY_SRCBLT, &ddck);
		//psurf->SetColorKey(DDCKEY_SRCBLT, &ddck);
	}
	else
		psurf = NULL;

	return psurf;
}
Exemplo n.º 8
0
//	DDRestoreCanvas
//	----------------------------------------------------------------------------
BOOL DDRestoreCanvas(dd_grs_canvas *canvas)
{
	HRESULT ddresult;
	
	Assert(canvas->lpdds != NULL);
	
	ddresult = IDirectDrawSurface_Restore(canvas->lpdds);
	if (ddresult != DD_OK) {
		if (ddresult != DDERR_WRONGMODE) {
			logentry("DDRAW::RestoreCanvas::Surface err: %x\n", ddresult);		
			return FALSE;
		}
		mprintf((0, "Recreating surfaces:\n"));
	// Must recreate canvas
		if (canvas->lpdds == _lpDDSPrimary || canvas->lpdds == _lpDDSBack) {
			mprintf((0, "DDRestoreCanvas::Screen memory was lost!\n"));
			exit(1);
		}
		if (canvas->sram) {
		// force sysmem canvas!
			canvas->lpdds = DDCreateSysMemSurface(canvas->canvas.cv_bitmap.bm_w,
											canvas->canvas.cv_bitmap.bm_h);
		}
		else {
			canvas->lpdds = DDCreateSurface(canvas->canvas.cv_bitmap.bm_w, 
											canvas->canvas.cv_bitmap.bm_h,
											_DDSysMemSurfacing);
		}					
	}
	return TRUE;
}
Exemplo n.º 9
0
static void * Lock( win32_driver_t * win32_driver, void * surface )
{
  LPDIRECTDRAWSURFACE	lock_surface = ( LPDIRECTDRAWSURFACE ) surface;
  HRESULT		result;

  if( !surface )
    return 0;

  memset( &win32_driver->ddsd, 0, sizeof( win32_driver->ddsd ) );
  win32_driver->ddsd.dwSize = sizeof( win32_driver->ddsd );

  result = IDirectDrawSurface_Lock( lock_surface, 0, &win32_driver->ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 );
  if( result == DDERR_SURFACELOST )
    {
      IDirectDrawSurface_Restore( lock_surface );
      result = IDirectDrawSurface_Lock( lock_surface, 0, &win32_driver->ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 );

      if( result != DD_OK )
	return 0;

    }
  else if( result != DD_OK )
    {
      if( result == DDERR_GENERIC )
	{
	  Error( 0, "surface->Lock : error, DDERR_GENERIC" );
	  exit( 1 );
	}
    }

  return win32_driver->ddsd.lpSurface;
}
Exemplo n.º 10
0
static void flip_page(void)
{
    DDSURFACEDESC2 ddsd;
    HRESULT dxresult;

    IDirectDrawSurface_Unlock(g_lpddsBack, NULL);

    if (g_doublebuffer) {
        dxresult = IDirectDrawSurface_Flip(g_lpddsOverlay, NULL, DDFLIP_WAIT);
        if (dxresult == DDERR_SURFACELOST) {
            av_log(NULL, AV_LOG_INFO, "vo_directx: Lost, Restoring Surface\n");
            IDirectDrawSurface_Restore(g_lpddsBack);
            IDirectDrawSurface_Restore(g_lpddsOverlay);
            IDirectDrawSurface_Restore(g_lpddsPrimary);
            dxresult = IDirectDrawSurface_Flip(g_lpddsOverlay, NULL, DDFLIP_WAIT);
        }
        if (dxresult != DD_OK) {
            av_log(NULL, AV_LOG_ERROR, "vo_directx: can not flip page\n");
        }
    } else {
        DDBLTFX ddbltfx;
        memset(&ddbltfx, 0, sizeof(DDBLTFX));
        ddbltfx.dwSize = sizeof(DDBLTFX);
        ddbltfx.dwDDFX = DDBLTFX_NOTEARING;
        IDirectDrawSurface_Blt(g_lpddsPrimary, &rd, g_lpddsBack, NULL, DDBLT_WAIT,
                               &ddbltfx);
    }

    memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
    ddsd.dwSize = sizeof(DDSURFACEDESC2);
    if (IDirectDrawSurface_Lock(g_lpddsBack, NULL, &ddsd,
                                DDLOCK_NOSYSLOCK | DDLOCK_WAIT, NULL) == DD_OK) {
        if (tmp_image) {
            free(tmp_image);
            tmp_image = NULL;
        }
        g_dstride = ddsd.lPitch;
        g_image = ddsd.lpSurface;
    } else {
        if (!tmp_image) {
            av_log(NULL, AV_LOG_INFO,
                   "Locking the surface failed, rendering to a hidden surface!\n");
            tmp_image = g_image = calloc(1, g_image_height * g_dstride * 2);
        }
    }
}
Exemplo n.º 11
0
//	DDRestoreScreen
//		Restore screens 
//	----------------------------------------------------------------------------
int DDRestoreScreen()
{
	mprintf((1, "Need to Restore DDraw Page0 and Page1.\n"));
	if (!_lpDDSPrimary || IDirectDrawSurface_Restore(_lpDDSPrimary) !=DD_OK) {
		mprintf((1, "Warning: Unable to restore Primary Surface.\n"));
		return 0;
	}
	if (!GRMODEINFO(paged) && _lpDDSBack) {
		if (IDirectDrawSurface_Restore(_lpDDSBack) != DD_OK) {
			mprintf((1, "Warning: Unable to restore Back Surface.\n"));
			return 0;
		}
	}
	else if (!_DDFullScreen) {
		if (!_lpDDSBack || IDirectDrawSurface_Restore(_lpDDSBack) != DD_OK) {
			mprintf((1, "Warning: Unable to restore Back Surface.\n"));
			return 0;
		}
	}

	return 1;
}
Exemplo n.º 12
0
//	DDSetPalette
//	----------------------------------------------------------------------------
void DDSetPalette(LPDIRECTDRAWPALETTE lpDDPal)
{
	HRESULT ddresult;

	ddresult = IDirectDrawSurface_SetPalette(_lpDDSPrimary, lpDDPal);
	if (ddresult != DD_OK) {
		if (ddresult == DDERR_SURFACELOST) {
			IDirectDrawSurface_Restore(_lpDDSPrimary);
			IDirectDrawSurface_SetPalette(_lpDDSPrimary, lpDDPal);
		}
		else {
			Error("Unable to attach palette to primary surface: %x.", ddresult);
		}
	}
}
Exemplo n.º 13
0
//
// Lock surface before multiple drawings by hand, for speed
//
boolean LockScreen(VOID)
{
	DDSURFACEDESC ddsd;
	HRESULT ddrval;

	ZeroMemory(&ddsd, sizeof (ddsd));
	ddsd.dwSize = sizeof (ddsd);

	// attempt to Lock the surface
	ddrval = IDirectDrawSurface_Lock(ScreenVirtual, NULL, &ddsd, DDLOCK_WAIT, NULL);

	// Always, always check for errors with DirectX!
	// If the surface was lost, restore it.
	if (ddrval == DDERR_SURFACELOST)
	{
		ddrval = IDirectDrawSurface_Restore(ScreenReal);

		// now retry to get the lock
		ddrval = IDirectDrawSurface_Lock(ScreenVirtual, NULL, &ddsd, DDLOCK_WAIT, NULL);
	}

	if (ddrval == DD_OK)
	{
		ScreenLocked = TRUE;
		ScreenPtr    = (LPBYTE)ddsd.lpSurface;
		ScreenPitch = ddsd.
#ifdef DUMMYUNIONNAMEN
		 DUMMYUNIONNAMEN(1).
#endif
		 lPitch;
	}
	else
	{
		ScreenLocked = FALSE;
		ScreenPtr = NULL;
		ScreenPitch = 0;
		//I_Error("LockScreen() : couldn't restore the surface.");
		return false;
	}
	return true;
}
Exemplo n.º 14
0
Arquivo: ddgfx.c Projeto: btb/d2x
int dd_gfx_loadbitmap2D(unsigned short handle, void *buf, int rleflag)
{
	HRESULT ddresult;
	DDSURFACEDESC ddsd;
	char *ptr;
	int pitch, i;
	grs_bitmap tbmp;

	Assert(handle != 0);

	if (!dd_gfx_initialized) return 0;

	handle--;									// Convert to valid handle

RedoLock:

	memset(&ddsd, 0, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);

	ddresult = IDirectDrawSurface_Lock(gfxBitmap[handle].lpdds, NULL,	&ddsd, DDLOCK_WAIT, NULL);
	if (ddresult != DD_OK) {
		if (ddresult == DDERR_SURFACELOST) {
			ddresult = IDirectDrawSurface_Restore(gfxBitmap[handle].lpdds);
			if (ddresult != DD_OK) {
				if (ddresult != DDERR_WRONGMODE) {
					logentry("DDGFX::Restore::Surface err: %x\n", ddresult);		
					return 1;
				}
				else {
					LPDIRECTDRAWSURFACE lpdds;
					DDCOLORKEY ddck;

					IDirectDrawSurface_Release(lpdds);
					gfxBitmap[handle].lpdds = NULL;

					memset(&ddsd, 0, sizeof(ddsd));
					ddsd.dwSize = sizeof(ddsd);
					ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
					ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
					ddsd.dwWidth = gfxBitmap[handle].w;
					ddsd.dwHeight = gfxBitmap[handle].h;

					ddresult = IDirectDraw_CreateSurface(_lpDD, &ddsd, &lpdds, NULL);

					if (ddresult != DD_OK) {
						mprintf((0, "DDGFX: Failed to restore vidmem 2d bitmap.\n"));
						return 1;
					}
   				ddck.dwColorSpaceLowValue = TRANSPARENCY_COLOR;
   				ddck.dwColorSpaceHighValue = TRANSPARENCY_COLOR;
   				IDirectDrawSurface_SetColorKey(lpdds, DDCKEY_SRCBLT, &ddck);
					gfxBitmap[handle].lpdds = lpdds;
				}
			}
			
			goto RedoLock;
		}
		else {
			mprintf((0, "DDGFX:Unable to lock surface!!\n"));
			return 1;
		}
	}

//	Locked!
	ptr = ddsd.lpSurface;
	pitch = ddsd.lPitch;	

	gr_init_bitmap(&tbmp, BM_LINEAR, 0,0,gfxBitmap[handle].w, gfxBitmap[handle].h, gfxBitmap[handle].w, buf);
	if (rleflag) tbmp.bm_flags = BM_FLAG_RLE;

	for(i = 0; i < gfxBitmap[handle].h; i++) 
	{
		extern ubyte scale_rle_data[];
		if (rleflag) {
			decode_row(&tbmp,i);
			memcpy(ptr+(i*pitch), scale_rle_data, gfxBitmap[handle].w);
		} 
	  	else memcpy(ptr+(i*pitch), (ubyte*)(buf)+(i*gfxBitmap[handle].w), gfxBitmap[handle].w);
	}
	
	IDirectDrawSurface_Unlock(gfxBitmap[handle].lpdds, ptr);

//	Unlocked...

	return 0;
}
Exemplo n.º 15
0
static long FAR PASCAL
WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	LPCREATESTRUCT lpcs;
	PAINTSTRUCT ps;
	RECT dirty;
	HDC hdc;
	struct ggi_visual *vis = (struct ggi_visual *) GetWindowLong(hWnd, GWL_USERDATA);
	directx_priv *priv = NULL;
	HRESULT hr;

	if (vis)
		priv = GGIDIRECTX_PRIV(vis);

	switch (message) {

	case WM_DDSETPALETTE:
		{
			int setpalette;
			GGI_directx_Lock(priv->spincs);
			setpalette = priv->setpalette;
			GGI_directx_Unlock(priv->spincs);
			if(setpalette)
				/* setpalette canceled */
				return 0;
		}
		if(GGI_directx_TryLock(priv->cs)) {
			/* spin */
			PostMessage(hWnd, message, wParam, lParam);
			return 0;
		}
		if(priv->lpddp)
			GGI_directx_DDChangePalette(vis);
		GGI_directx_Lock(priv->spincs);
		priv->setpalette = 1;
		GGI_directx_Unlock(priv->spincs);
		GGI_directx_Unlock(priv->cs);
		return 0;

	case WM_TIMER:
		if (wParam != 1)
			break;
		if (GGI_directx_TryLock(priv->cs)) {
			int redraw = 0;
			GGI_directx_Lock(priv->spincs);
			redraw = priv->redraw;
			priv->redraw = 0;
			GGI_directx_Unlock(priv->spincs);
			if (redraw)
				/* spin */
				PostMessage(hWnd, WM_USER, wParam, lParam);
			return 0;
		}
		GGI_directx_DDRedrawAll(vis);
		GGI_directx_Unlock(priv->cs);
		return 0;

	case WM_PAINT:
		if (GGI_directx_TryLock(priv->cs)) {
			int redraw = 0;
			GGI_directx_Lock(priv->spincs);
			redraw = priv->redraw;
			priv->redraw = 0;
			GGI_directx_Unlock(priv->spincs);
			if (redraw)
				/* spin */
				InvalidateRect(hWnd, NULL, 0);
			return 0;
		}
		if (GetUpdateRect(hWnd, &dirty, FALSE)) {
			/* I have a back buffer to update from,
			 * no need to involve the application...
			if (priv->inp) {
				gii_event ev;

				ev.any.size = sizeof(gii_expose_event);
				ev.any.type = evExpose;
				ev.any.target = priv->inp->origin;
				ev.expose.x = vis->origin_x + dirty.left;
				ev.expose.y = vis->origin_y + dirty.top;
				ev.expose.w = dirty.right - dirty.left;
				ev.expose.h = dirty.bottom - dirty.top;

				giiEventSend(priv->inp, &ev);
			}
			*/
			hr = IDirectDrawSurface_IsLost(priv->lppdds);
			if (hr == DDERR_SURFACELOST)
				hr = IDirectDrawSurface_Restore(
					priv->lppdds);

			hdc = BeginPaint(hWnd, &ps);
			GGI_directx_DDRedraw(
				vis,
				vis->origin_x + ps.rcPaint.left,
				vis->origin_y + ps.rcPaint.top,
				ps.rcPaint.right - ps.rcPaint.left,
				ps.rcPaint.bottom - ps.rcPaint.top);
			EndPaint(hWnd, &ps);
		}
		GGI_directx_Unlock(priv->cs);
		return 0;

	case WM_SIZING:
		GGI_directx_Lock(priv->sizingcs);
		if (priv->xstep < 0) {
			GGI_directx_Unlock(priv->sizingcs);
			break;
		}
		DDSizing(vis, wParam, (LPRECT) lParam);
		GGI_directx_Unlock(priv->sizingcs);
		return TRUE;

	case WM_SIZE:
		switch(wParam) {
		case SIZE_MAXIMIZED:
		case SIZE_RESTORED:
			break;
		default:
			return 0;
		}
		GGI_directx_Lock(priv->sizingcs);
		if (priv->xstep < 0) {
			GGI_directx_Unlock(priv->sizingcs);
			break;
		}
		DDNotifyResize(vis, LOWORD(lParam), HIWORD(lParam));
		GGI_directx_Unlock(priv->sizingcs);
		return 0;

	case WM_QUERYNEWPALETTE:
		if(GGI_directx_TryLock(priv->cs)) {
			int setpalette = 0;
			GGI_directx_Lock(priv->spincs);
			setpalette = priv->setpalette;
			priv->redraw = 0;
			GGI_directx_Unlock(priv->spincs);
			if(setpalette)
				/* spin */
				PostMessage(hWnd, WM_DDSETPALETTE,
					wParam, lParam);
			return 0;
		}
		if(!priv->lpddp) {
			GGI_directx_Unlock(priv->cs);
			break;
		}
		GGI_directx_DDChangePalette(vis);
		GGI_directx_Unlock(priv->cs);
		return TRUE;

	case WM_CREATE:
		lpcs = (LPCREATESTRUCT) lParam;
		SetWindowLong(hWnd,
			      GWL_USERDATA, (DWORD) lpcs->lpCreateParams);
		return 0;

	case WM_CLOSE:
		DPRINT_EVENTS("WM_CLOSE\n");
		if (priv->hParent)
			break;

		ggBroadcast(vis->instance.channel, GGI_CMDCODE_CLOSE, NULL);

		if (priv->exit_on_close_window)
			exit(0);
		return 0;

	case WM_RENDERFORMAT:
	case WM_RENDERALLFORMATS:
		{
			struct ggi_directx_cmddata_render_cb format;
			format.format = wParam;

			ggBroadcast(vis->instance.channel,
				GGI_DIRECTX_RENDERCLIPBOARD, &format);
			return 0;
		}

	case WM_DESTROYCLIPBOARD:
		ggBroadcast(vis->instance.channel,
			GGI_DIRECTX_DESTROYCLIPBOARD, NULL);
		return 0;

#if 0 /* WM_CLIPBOARDUPDATE is >= Vista :-( */
	case WM_CLIPBOARDUPDATE:
		ggBroadcast(vis->instance.channel,
			GGI_DIRECTX_CLIPBOARDUPDATE, NULL);
		return 0;
#endif

	case WM_SETTINGCHANGE:
		GGI_directx_Lock(priv->cs);
		if (priv->settings_changed) {
			DPRINT("tell inputlib about "
				"new system parameters\n");
			priv->settings_changed(priv->settings_changed_arg);
			GGI_directx_Unlock(priv->cs);
			return 0;
		}
		GGI_directx_Unlock(priv->cs);
		break;

	case WM_SETFOCUS:
		if (priv->grab_hotkeys) {
			DPRINT("Grab hotkeys (focus)\n");
			PostThreadMessage(priv->nThreadID, WM_DDHOTKEY, 1, 0);
		}
		priv->focus = 1;
		break;

	case WM_KILLFOCUS:
		if (priv->grab_hotkeys) {
			DPRINT("Ungrab hotkeys (unfocus)\n");
			PostThreadMessage(priv->nThreadID, WM_DDHOTKEY, 0, 0);
		}
		priv->focus = 0;
		break;

	case WM_HOTKEY:
		if (priv->grab_hotkeys && priv->inp) {
			gii_inputdx_hotkey hotkey;
			hotkey.id = wParam;
			hotkey.mod = LOWORD(lParam);
			hotkey.vk = HIWORD(lParam);
			DPRINT("WM_HOTKEY id=%d, mod=%04x, vk=%d\n",
				hotkey.id, hotkey.mod, hotkey.vk);
			ggControl(priv->inp->channel, GII_INPUTDX_HOTKEY,
				&hotkey);
		}
		break;
	}
	return DefWindowProc(hWnd, message, wParam, lParam);
}