[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 */