[AD] DIFF for DirectX pageflip fix

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


I would like to submit this diff for evaluation, as I mentioned before,
it should fix incorrect pageflipping on cards like Voodoo3 and TNT2. I
really would appreciate feedback and testing on this.

I also made the colour palette setting more accurate (previously the
maximum 63 value was converted to 252 with <<2).
? mypatch.diff
Index: wddbmp.c
===================================================================
RCS file: /cvsroot/alleg/allegro/src/win/wddbmp.c,v
retrieving revision 1.2
diff -u -r1.2 wddbmp.c
--- wddbmp.c	2000/08/15 11:30:06	1.2
+++ wddbmp.c	2000/08/26 17:39:35
@@ -18,6 +18,9 @@
 #include "wddraw.h"
 
 
+static LPDIRECTDRAWSURFACE primbuffersurf = NULL;
+static LPDIRECTDRAWSURFACE backbuffersurf = NULL;
+static LPDIRECTDRAWSURFACE tripbuffersurf = NULL;
 
 static int OverlayMatch[] = { 8, 15, 16, 24, 24, 32, 32, 0 };
 
@@ -42,9 +45,16 @@
 /* sometimes we have to recycle the screen surface as a video bitmap,
  * in order to be consistent with how other platforms behave.
  */
-static int ReusedScreen = FALSE;
+static int ReusedScreen = 0;
 
 
+HRESULT WINAPI EnumSurfacesCallback (LPDIRECTDRAWSURFACE lpDDSurface,
+	LPDDSURFACEDESC lpDDSurfaceDesc,LPVOID lpContext)
+{
+	if (backbuffersurf == NULL) backbuffersurf = lpDDSurface;
+	if (tripbuffersurf == NULL) tripbuffersurf = lpDDSurface;
+	return DDENUMRET_OK;
+}
 
 /* gfx_directx_create_surface: 
  */ 
@@ -53,20 +63,28 @@
 {
    DDSURFACEDESC surf_desc;
    LPDIRECTDRAWSURFACE surf;
+   DDSCAPS ddscaps;
    HRESULT hr;
    unsigned int format=0;
 
 loop:
    /* describe surface characteristics */
+	memset (&surf_desc, 0, sizeof(DDSURFACEDESC));
    surf_desc.dwSize = sizeof(surf_desc);
    surf_desc.dwFlags = DDSD_CAPS;
    surf_desc.ddsCaps.dwCaps = 0;
 
+   if (primary == 2) return backbuffersurf;
+   if (primary == 3) return tripbuffersurf;
+
    if (video || primary) {
       surf_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
 
       if (primary) {
          surf_desc.ddsCaps.dwCaps |= DDSCAPS_PRIMARYSURFACE;
+	   surf_desc.dwFlags = DDSD_BACKBUFFERCOUNT;
+	   surf_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
+	   surf_desc.dwBackBufferCount = 2;
       }
       else if (overlay) {
          surf_desc.ddsCaps.dwCaps |= DDSCAPS_OVERLAY;
@@ -107,10 +125,35 @@
    if (FAILED(hr)) {
       if (video && !primary && overlay && OverlayMatch[++format] == color_depth)
          goto loop;
-      else
-         return NULL;
+      else {
+		if (primary) {
+			surf_desc.dwBackBufferCount = 1;
+			hr = IDirectDraw_CreateSurface(directdraw, &surf_desc, &surf, NULL);
+			if (FAILED(hr)) {
+				surf_desc.dwBackBufferCount = 0;
+				surf_desc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
+				hr = IDirectDraw_CreateSurface(directdraw, &surf_desc, &surf, NULL);
+				if (FAILED(hr)) return NULL;
+			}
+			primbuffersurf = surf;
+			return surf;
+		}
+		return NULL;
+	}
    }
 
+   /* get attached backbuffers */
+	if (surf_desc.dwBackBufferCount == 2) {
+		IDirectDrawSurface_EnumAttachedSurfaces(surf, NULL, EnumSurfacesCallback);
+		primbuffersurf = surf;
+	} else {
+	if (surf_desc.dwBackBufferCount == 1) {
+		memset (&ddscaps, 0, sizeof(DDSCAPS));
+		ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
+		hr = IDirectDrawSurface_GetAttachedSurface(surf, &ddscaps, &backbuffersurf);
+		primbuffersurf = surf;
+	} }
+
    return surf;
 }
 
@@ -243,11 +286,31 @@
    LPDIRECTDRAWSURFACE surf;
 
    /* can we reuse the screen bitmap for this? */
-   if ((!ReusedScreen) && (screen->w == width) && (screen->h == height)) {
-      ReusedScreen = TRUE;
-      return screen;
+   if ((ReusedScreen < 3) && (screen->w == width) && (screen->h == height)) {
+      ReusedScreen ++;
+      if (ReusedScreen == 1) return screen;
+      if (ReusedScreen == 2) {
+		if (backbuffersurf == NULL) return NULL;
+		return make_directx_bitmap (backbuffersurf,
+			width, height, _color_depth, BMP_ID_VIDEO);
+	}
+      if (ReusedScreen == 3) {
+		if (tripbuffersurf == NULL) return NULL;
+		return make_directx_bitmap (tripbuffersurf,
+			width, height, _color_depth, BMP_ID_VIDEO);
+	}
    }
 
+	/* assume all flip surfaces have been allocated, so free unused */
+	if (ReusedScreen < 3 && tripbuffersurf != NULL) {
+		IDirectDrawSurface_Release (tripbuffersurf);
+		tripbuffersurf = NULL;
+	}
+	if (ReusedScreen < 2 && backbuffersurf != NULL) {
+		IDirectDrawSurface_Release (backbuffersurf);
+		backbuffersurf = NULL;
+	}
+
    /* create DirectDraw surface */
    surf = gfx_directx_create_surface(width, height, _color_depth, 1, 0, 0);
    if (surf == NULL)
@@ -263,9 +326,10 @@
  */
 void gfx_directx_destroy_video_bitmap(struct BITMAP *bitmap)
 {
-   if (bitmap == screen) {
-      ReusedScreen = FALSE;
-      return;
+   if (bitmap == screen || BMP_EXTRA(bitmap)->surf == backbuffersurf ||
+	BMP_EXTRA(bitmap)->surf == tripbuffersurf) {
+	      ReusedScreen --;
+	      return;
    }
 
    if (bitmap == dd_frontbuffer)
@@ -290,6 +354,19 @@
    invisible = BMP_EXTRA(bitmap)->surf;
    visible = BMP_EXTRA(dd_frontbuffer)->surf;
 
+	/* try to flip already attached surfaces */
+   if (backbuffersurf != NULL &&
+	(invisible == primbuffersurf || invisible == backbuffersurf
+	|| invisible == tripbuffersurf)) {
+		hr = IDirectDrawSurface_Flip(primbuffersurf, invisible, 0);
+		if (FAILED(hr)) IDirectDrawSurface_Flip(primbuffersurf, invisible, DDFLIP_WAIT);
+      BMP_EXTRA(bitmap)->surf = visible;
+      BMP_EXTRA(dd_frontbuffer)->surf = invisible;
+      dd_frontbuffer = bitmap;
+	return 0;
+   }
+
+	/* original flipping system */
    if (visible != invisible) {
       /* link invisible surface to primary surface */
       hr = IDirectDrawSurface_AddAttachedSurface(visible, invisible);
Index: wddraw.c
===================================================================
RCS file: /cvsroot/alleg/allegro/src/win/wddraw.c,v
retrieving revision 1.2
diff -u -r1.2 wddraw.c
--- wddraw.c	2000/08/15 11:30:06	1.2
+++ wddraw.c	2000/08/26 17:39:46
@@ -22,6 +22,8 @@
 /* directx vars */
 LPDIRECTDRAW directdraw = NULL;
 LPDIRECTDRAWSURFACE dd_prim_surface = NULL;
+LPDIRECTDRAWSURFACE dd_back_surface = NULL;
+LPDIRECTDRAWSURFACE dd_trip_surface = NULL;
 LPDIRECTDRAWPALETTE dd_palette = NULL;
 LPDIRECTDRAWCLIPPER dd_clipper = NULL;
 DDCAPS dd_caps;
@@ -39,9 +41,9 @@
 
    /* convert into Windows format */
    for (n = from; n <= to; n++) {
-      _palette[n].peRed = p[n].r << 2;
-      _palette[n].peGreen = p[n].g << 2;
-      _palette[n].peBlue = p[n].b << 2;
+      _palette[n].peRed = (p[n].r << 2) | ((p[n].r & 0x30) >> 4);
+      _palette[n].peGreen = (p[n].g << 2) | ((p[n].g & 0x30) >> 4);
+      _palette[n].peBlue = (p[n].b << 2) | ((p[n].b & 0x30) >> 4);
    }
 
    /* wait for vertical retrace */
@@ -123,6 +125,8 @@
       _TRACE("Can't create primary surface.\n");
       return -1;
    }
+   dd_back_surface = gfx_directx_create_surface(w, h, color_depth, 1, 2, 0);
+   dd_trip_surface = gfx_directx_create_surface(w, h, color_depth, 1, 3, 0);
 
    return 0;
 }
@@ -236,6 +240,8 @@
    if (dd_prim_surface) {
       IDirectDrawSurface_Release(dd_prim_surface);
       dd_prim_surface = NULL;
+      dd_back_surface = NULL;
+      dd_trip_surface = NULL;
    }
 
    /* unlink surface from bitmap */


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/