- some clean up in handling of depth
- more depth conversion routines for X11 (15, 16 and 32 -> 8)
diff --git a/graphics/ddraw.c b/graphics/ddraw.c
index 75051d5..54d5627 100644
--- a/graphics/ddraw.c
+++ b/graphics/ddraw.c
@@ -416,47 +416,6 @@
pf->y.dwRBitMask, pf->z.dwGBitMask, pf->xx.dwBBitMask, pf->xy.dwRGBAlphaBitMask);
}
-static int _getpixelformat(LPDIRECTDRAW2 ddraw,LPDDPIXELFORMAT pf) {
- static XVisualInfo *vi;
- XVisualInfo vt;
- int nitems;
-
- if (!vi)
- vi = TSXGetVisualInfo(display,VisualNoMask,&vt,&nitems);
-
- pf->dwFourCC = 0;
- pf->dwSize = sizeof(DDPIXELFORMAT);
- if (ddraw->d.depth==8) {
- pf->dwFlags = DDPF_RGB|DDPF_PALETTEINDEXED8;
- pf->x.dwRGBBitCount = 8;
- pf->y.dwRBitMask = 0;
- pf->z.dwGBitMask = 0;
- pf->xx.dwBBitMask = 0;
- pf->xy.dwRGBAlphaBitMask= 0;
- return 0;
- }
- if (ddraw->d.depth==16) {
- pf->dwFlags = DDPF_RGB;
- pf->x.dwRGBBitCount = 16;
- pf->y.dwRBitMask = vi[0].red_mask;
- pf->z.dwGBitMask = vi[0].green_mask;
- pf->xx.dwBBitMask = vi[0].blue_mask;
- pf->xy.dwRGBAlphaBitMask= 0;
- return 0;
- }
- if (ddraw->d.depth==24) {
- pf->dwFlags = DDPF_RGB;
- pf->x.dwRGBBitCount = 24;
- pf->y.dwRBitMask = vi[0].red_mask;
- pf->z.dwGBitMask = vi[0].green_mask;
- pf->xx.dwBBitMask = vi[0].blue_mask;
- pf->xy.dwRGBAlphaBitMask= 0;
- return 0;
- }
- FIXME(ddraw,"_getpixelformat:unknown depth %ld?\n",ddraw->d.depth);
- return DDERR_GENERIC;
-}
-
/******************************************************************************
* IDirectDrawSurface methods
*
@@ -500,29 +459,13 @@
}
static void Xlib_copy_surface_on_screen(LPDIRECTDRAWSURFACE4 this) {
- if (this->s.ddraw->d.depth != this->s.ddraw->d.screen_depth) {
- /* Pixel convertion ! */
- if ((this->s.ddraw->d.depth == 8) && (this->s.ddraw->d.screen_depth == 16)) {
- unsigned char *src = (unsigned char *) this->s.surface_desc.y.lpSurface;
- unsigned short *dst = (unsigned short *) this->t.xlib.image->data;
- unsigned short *pal;
- int x, y;
-
- if (this->s.palette != NULL) {
- pal = (unsigned short *) this->s.palette->screen_palents;
- for (y = 0; y < this->s.surface_desc.dwHeight; y++) {
- for (x = 0; x < this->s.surface_desc.dwWidth; x++) {
- dst[x + y * this->s.surface_desc.lPitch] = pal[src[x + y * this->s.surface_desc.lPitch]];
- }
- }
- } else {
- WARN(ddraw, "No palette set...\n");
- memset(dst, 0, this->s.surface_desc.lPitch * this->s.surface_desc.dwHeight * 2);
- }
- } else {
- ERR(ddraw, "Unsupported pixel convertion...\n");
- }
- }
+ if (this->s.ddraw->d.pixel_convert != NULL)
+ this->s.ddraw->d.pixel_convert(this->s.surface_desc.y.lpSurface,
+ this->t.xlib.image->data,
+ this->s.surface_desc.dwWidth,
+ this->s.surface_desc.dwHeight,
+ this->s.surface_desc.lPitch,
+ this->s.palette);
#ifdef HAVE_LIBXXSHM
if (this->s.ddraw->e.xlib.xshm_active)
@@ -652,7 +595,7 @@
return DD_OK;
}
- if( !(pal->cm) && (this->s.ddraw->d.screen_depth<=8))
+ if( !(pal->cm) && (this->s.ddraw->d.screen_pixelformat.x.dwRGBBitCount<=8))
{
pal->cm = TSXCreateColormap(display,this->s.ddraw->d.drawable,
DefaultVisualOfScreen(X11DRV_GetXScreen()),AllocAll);
@@ -1031,6 +974,10 @@
DUMP(" caps: ");
_dump_DDSCAPS(ddsd->ddsCaps.dwCaps);
}
+ if (ddsd->dwFlags & DDSD_PIXELFORMAT) {
+ DUMP(" pixel format : \n");
+ _dump_pixelformat(&(ddsd->ddpfPixelFormat));
+ }
}
return DD_OK;
@@ -1076,7 +1023,7 @@
this->s.backbuffer->lpvtbl->fnRelease(this->s.backbuffer);
if (this->t.xlib.image != NULL) {
- if (this->s.ddraw->d.depth != this->s.ddraw->d.screen_depth) {
+ if (this->s.ddraw->d.pixel_convert != NULL) {
/* In pixel conversion mode, there are two buffers to release... */
HeapFree(GetProcessHeap(),0,this->s.surface_desc.y.lpSurface);
@@ -1810,28 +1757,9 @@
}
/* Now, if we are in 'depth conversion mode', update the screen palette */
- if (this->ddraw->d.depth != this->ddraw->d.screen_depth) {
- int i;
+ if (this->ddraw->d.palette_convert != NULL)
+ this->ddraw->d.palette_convert(palent, this->screen_palents, start, count);
- switch (this->ddraw->d.screen_depth) {
- case 16: {
- unsigned short *screen_palette = (unsigned short *) this->screen_palents;
-
- for (i = 0; i < count; i++) {
- screen_palette[start + i] = (((((unsigned short) palent[i].peRed) & 0xF8) << 8) |
- ((((unsigned short) palent[i].peBlue) & 0xF8) >> 3) |
- ((((unsigned short) palent[i].peGreen) & 0xFC) << 3));
- }
- } break;
-
- default:
- ERR(ddraw, "Memory corruption !\n");
- break;
- }
- }
-
- if (!this->cm) /* should not happen */ {
- }
return DD_OK;
}
@@ -2232,7 +2160,7 @@
/* This is a standard image */
if (!(lpddsd->dwFlags & DDSD_PIXELFORMAT)) {
/* No pixel format => use DirectDraw's format */
- _getpixelformat(this,&(lpddsd->ddpfPixelFormat));
+ lpddsd->ddpfPixelFormat = this->d.directdraw_pixelformat;
lpddsd->dwFlags |= DDSD_PIXELFORMAT;
} else {
/* To check what the program wants */
@@ -2302,19 +2230,19 @@
/* if i == 32 or maximum ... return error */
this->e.dga.vpmask|=(1<<i);
(*lpdsf)->s.surface_desc.y.lpSurface =
- this->e.dga.fb_addr+((i*this->e.dga.fb_height)*this->e.dga.fb_width*this->d.depth/8);
+ this->e.dga.fb_addr+((i*this->e.dga.fb_height)*this->e.dga.fb_width*this->d.directdraw_pixelformat.x.dwRGBBitCount/8);
(*lpdsf)->t.dga.fb_height = i*this->e.dga.fb_height;
- (*lpdsf)->s.surface_desc.lPitch = this->e.dga.fb_width*this->d.depth/8;
+ (*lpdsf)->s.surface_desc.lPitch = this->e.dga.fb_width*this->d.directdraw_pixelformat.x.dwRGBBitCount/8;
lpddsd->lPitch = (*lpdsf)->s.surface_desc.lPitch;
/* Add flags if there were not present */
- (*lpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE;
+ (*lpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE|DDSD_PIXELFORMAT;
(*lpdsf)->s.surface_desc.dwWidth = this->d.width;
(*lpdsf)->s.surface_desc.dwHeight = this->d.height;
TRACE(ddraw,"primary surface: dwWidth=%ld, dwHeight=%ld, lPitch=%ld\n",this->d.width,this->d.height,lpddsd->lPitch);
/* We put our surface always in video memory */
(*lpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VISIBLE|DDSCAPS_VIDEOMEMORY;
- _getpixelformat(this,&((*lpdsf)->s.surface_desc.ddpfPixelFormat));
+ (*lpdsf)->s.surface_desc.ddpfPixelFormat = this->d.directdraw_pixelformat;
(*lpdsf)->s.backbuffer = NULL;
if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
@@ -2340,7 +2268,7 @@
back->s.surface_desc = (*lpdsf)->s.surface_desc;
/* Change the parameters that are not the same */
back->s.surface_desc.y.lpSurface = this->e.dga.fb_addr+
- ((i*this->e.dga.fb_height)*this->e.dga.fb_width*this->d.depth/8);
+ ((i*this->e.dga.fb_height)*this->e.dga.fb_width*this->d.directdraw_pixelformat.x.dwRGBBitCount/8);
back->s.ddraw = this;
back->s.backbuffer = NULL; /* does not have a backbuffer, it is
* one! */
@@ -2377,7 +2305,7 @@
img = TSXShmCreateImage(display,
DefaultVisualOfScreen(X11DRV_GetXScreen()),
- this->d.screen_depth,
+ this->d.pixmap_depth,
ZPixmap,
NULL,
&(lpdsf->t.xlib.shminfo),
@@ -2448,11 +2376,11 @@
shmctl(lpdsf->t.xlib.shminfo.shmid, IPC_RMID, 0);
- if (this->d.depth != this->d.screen_depth) {
+ if (this->d.pixel_convert != NULL) {
lpdsf->s.surface_desc.y.lpSurface = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
lpdsf->s.surface_desc.dwWidth *
lpdsf->s.surface_desc.dwHeight *
- (this->d.depth / 8));
+ (this->d.directdraw_pixelformat.x.dwRGBBitCount));
} else {
lpdsf->s.surface_desc.y.lpSurface = img->data;
}
@@ -2476,13 +2404,13 @@
lpdsf->s.surface_desc.y.lpSurface = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
lpdsf->s.surface_desc.dwWidth *
lpdsf->s.surface_desc.dwHeight *
- (this->d.depth / 8));
+ (this->d.directdraw_pixelformat.x.dwRGBBitCount / 8));
- if (this->d.depth != this->d.screen_depth) {
+ if (this->d.pixel_convert != NULL) {
img_data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
lpdsf->s.surface_desc.dwWidth *
lpdsf->s.surface_desc.dwHeight *
- (this->d.screen_depth / 8));
+ (this->d.screen_pixelformat.x.dwRGBBitCount / 8));
} else {
img_data = lpdsf->s.surface_desc.y.lpSurface;
}
@@ -2491,21 +2419,21 @@
img =
TSXCreateImage(display,
DefaultVisualOfScreen(X11DRV_GetXScreen()),
- this->d.screen_depth,
+ this->d.pixmap_depth,
ZPixmap,
0,
img_data,
lpdsf->s.surface_desc.dwWidth,
lpdsf->s.surface_desc.dwHeight,
32,
- lpdsf->s.surface_desc.dwWidth * (this->d.screen_depth / 8)
+ lpdsf->s.surface_desc.dwWidth * (this->d.screen_pixelformat.x.dwRGBBitCount / 8)
);
#ifdef HAVE_LIBXXSHM
}
#endif
- if (this->d.depth != this->d.screen_depth) {
- lpdsf->s.surface_desc.lPitch = (this->d.depth / 8) * lpdsf->s.surface_desc.dwWidth;
+ if (this->d.pixel_convert != NULL) {
+ lpdsf->s.surface_desc.lPitch = (this->d.directdraw_pixelformat.x.dwRGBBitCount / 8) * lpdsf->s.surface_desc.dwWidth;
} else {
lpdsf->s.surface_desc.lPitch = img->bytes_per_line;
}
@@ -2557,11 +2485,11 @@
(*lpdsf)->t.xlib.image = img;
/* Add flags if there were not present */
- (*lpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE;
+ (*lpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE|DDSD_PIXELFORMAT;
(*lpdsf)->s.surface_desc.dwWidth = this->d.width;
(*lpdsf)->s.surface_desc.dwHeight = this->d.height;
(*lpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VISIBLE|DDSCAPS_VIDEOMEMORY;
- _getpixelformat(this,&((*lpdsf)->s.surface_desc.ddpfPixelFormat));
+ (*lpdsf)->s.surface_desc.ddpfPixelFormat = this->d.directdraw_pixelformat;
(*lpdsf)->s.backbuffer = NULL;
/* Check for backbuffers */
@@ -2703,34 +2631,122 @@
SetFocus(this->d.window);
}
+static int _common_depth_to_pixelformat(DWORD depth, DDPIXELFORMAT *pixelformat, DDPIXELFORMAT *screen_pixelformat, int *pix_depth) {
+ XVisualInfo *vi;
+ XPixmapFormatValues *pf;
+ XVisualInfo vt;
+ int nvisuals, npixmap, i;
+ int match = 0;
+
+ vi = TSXGetVisualInfo(display, VisualNoMask, &vt, &nvisuals);
+ pf = XListPixmapFormats(display, &npixmap);
+
+ for (i = 0; i < npixmap; i++) {
+ if (pf[i].bits_per_pixel == depth) {
+ int j;
+
+ for (j = 0; j < nvisuals; j++) {
+ if (vi[j].depth == pf[i].depth) {
+ pixelformat->dwSize = sizeof(*pixelformat);
+ if (depth == 8) {
+ pixelformat->dwFlags = DDPF_PALETTEINDEXED8;
+ pixelformat->y.dwRBitMask = 0;
+ pixelformat->z.dwGBitMask = 0;
+ pixelformat->xx.dwBBitMask = 0;
+ } else {
+ pixelformat->dwFlags = DDPF_RGB;
+ pixelformat->y.dwRBitMask = vi[j].red_mask;
+ pixelformat->z.dwGBitMask = vi[j].green_mask;
+ pixelformat->xx.dwBBitMask = vi[j].blue_mask;
+ }
+ pixelformat->dwFourCC = 0;
+ pixelformat->x.dwRGBBitCount = pf[i].bits_per_pixel;
+ pixelformat->xy.dwRGBAlphaBitMask= 0;
+
+ *screen_pixelformat = *pixelformat;
+
+ if (pix_depth != NULL)
+ *pix_depth = vi[j].depth;
+
+ match = 1;
+
+ break;
+ }
+ }
+
+ if (j == nvisuals)
+ ERR(ddraw, "No visual corresponding to pixmap format !\n");
+ }
+ }
+
+ if ((match == 0) && (depth == 8)) {
+ pixelformat->dwSize = sizeof(*pixelformat);
+ pixelformat->dwFlags = DDPF_PALETTEINDEXED8;
+ pixelformat->dwFourCC = 0;
+ pixelformat->x.dwRGBBitCount = 8;
+ pixelformat->y.dwRBitMask = 0;
+ pixelformat->z.dwGBitMask = 0;
+ pixelformat->xx.dwBBitMask = 0;
+ pixelformat->xy.dwRGBAlphaBitMask= 0;
+
+ /* In that case, find a visual to emulate the 8 bpp format */
+ for (i = 0; i < npixmap; i++) {
+ if (pf[i].bits_per_pixel >= depth) {
+ int j;
+
+ for (j = 0; j < nvisuals; j++) {
+ if (vi[j].depth == pf[i].depth) {
+ screen_pixelformat->dwSize = sizeof(*screen_pixelformat);
+ screen_pixelformat->dwFlags = DDPF_RGB;
+ screen_pixelformat->dwFourCC = 0;
+ screen_pixelformat->x.dwRGBBitCount = pf[i].bits_per_pixel;
+ screen_pixelformat->y.dwRBitMask = vi[j].red_mask;
+ screen_pixelformat->z.dwGBitMask = vi[j].green_mask;
+ screen_pixelformat->xx.dwBBitMask = vi[j].blue_mask;
+ screen_pixelformat->xy.dwRGBAlphaBitMask= 0;
+
+ if (pix_depth != NULL)
+ *pix_depth = vi[j].depth;
+
+ match = 2;
+
+ break;
+ }
+ }
+
+ if (j == nvisuals)
+ ERR(ddraw, "No visual corresponding to pixmap format !\n");
+ }
+ }
+ }
+
+ TSXFree(vi);
+ TSXFree(pf);
+
+ return match;
+}
+
static HRESULT WINAPI DGA_IDirectDraw_SetDisplayMode(
LPDIRECTDRAW this,DWORD width,DWORD height,DWORD depth
) {
#ifdef HAVE_LIBXXF86DGA
- int i,*depths,depcount,mode_count;
+ int i,mode_count;
TRACE(ddraw, "(%p)->(%ld,%ld,%ld)\n", this, width, height, depth);
/* We hope getting the asked for depth */
- this->d.screen_depth = depth;
-
- depths = TSXListDepths(display,DefaultScreen(display),&depcount);
-
- for (i=0;i<depcount;i++)
- if (depths[i]==depth)
- break;
- TSXFree(depths);
- if (i==depcount) {/* not found */
+ if (_common_depth_to_pixelformat(depth, &(this->d.directdraw_pixelformat), &(this->d.screen_pixelformat), NULL) != 1) {
+ /* I.e. no visual found or emulated */
ERR(ddraw,"(w=%ld,h=%ld,d=%ld), unsupported depth!\n",width,height,depth);
return DDERR_UNSUPPORTEDMODE;
}
+
if (this->d.width < width) {
ERR(ddraw,"SetDisplayMode(w=%ld,h=%ld,d=%ld), width %ld exceeds framebuffer width %ld\n",width,height,depth,width,this->d.width);
return DDERR_UNSUPPORTEDMODE;
}
this->d.width = width;
this->d.height = height;
- this->d.depth = depth;
/* adjust fb_height, so we don't overlap */
if (this->e.dga.fb_height < height)
@@ -2805,43 +2821,155 @@
#endif /* defined(HAVE_LIBXXF86DGA) */
}
+/* *************************************
+ 16 / 15 bpp to palettized 8 bpp
+ ************************************* */
+static void pixel_convert_16_to_8(void *src, void *dst, DWORD width, DWORD height, LONG pitch, LPDIRECTDRAWPALETTE palette) {
+ unsigned char *c_src = (unsigned char *) src;
+ unsigned short *c_dst = (unsigned short *) dst;
+ int x, y;
+
+ if (palette != NULL) {
+ unsigned short *pal = (unsigned short *) palette->screen_palents;
+
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ c_dst[x + y * width] = pal[c_src[x + y * pitch]];
+ }
+ }
+ } else {
+ WARN(ddraw, "No palette set...\n");
+ memset(dst, 0, width * height * 2);
+ }
+}
+static void palette_convert_16_to_8(LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count) {
+ int i;
+ unsigned short *pal = (unsigned short *) screen_palette;
+
+ for (i = 0; i < count; i++)
+ pal[start + i] = (((((unsigned short) palent[i].peRed) & 0xF8) << 8) |
+ ((((unsigned short) palent[i].peBlue) & 0xF8) >> 3) |
+ ((((unsigned short) palent[i].peGreen) & 0xFC) << 3));
+}
+static void palette_convert_15_to_8(LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count) {
+ int i;
+ unsigned short *pal = (unsigned short *) screen_palette;
+
+ for (i = 0; i < count; i++)
+ pal[start + i] = (((((unsigned short) palent[i].peRed) & 0xF8) << 7) |
+ ((((unsigned short) palent[i].peBlue) & 0xF8) >> 3) |
+ ((((unsigned short) palent[i].peGreen) & 0xF8) << 2));
+}
+
+/* *************************************
+ 24 / 32 bpp to palettized 8 bpp
+ ************************************* */
+static void pixel_convert_32_to_8(void *src, void *dst, DWORD width, DWORD height, LONG pitch, LPDIRECTDRAWPALETTE palette) {
+ unsigned char *c_src = (unsigned char *) src;
+ unsigned int *c_dst = (unsigned int *) dst;
+ int x, y;
+
+ if (palette != NULL) {
+ unsigned int *pal = (unsigned int *) palette->screen_palents;
+
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ c_dst[x + y * width] = pal[c_src[x + y * pitch]];
+ }
+ }
+ } else {
+ WARN(ddraw, "No palette set...\n");
+ memset(dst, 0, width * height * 4);
+ }
+}
+static void palette_convert_24_to_8(LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count) {
+ int i;
+ unsigned int *pal = (unsigned int *) screen_palette;
+
+ for (i = 0; i < count; i++)
+ pal[start + i] = ((((unsigned int) palent[i].peRed) << 16) |
+ (((unsigned int) palent[i].peGreen) << 8) |
+ ((unsigned int) palent[i].peBlue));
+}
+
static HRESULT WINAPI Xlib_IDirectDraw_SetDisplayMode(
LPDIRECTDRAW this,DWORD width,DWORD height,DWORD depth
) {
- int i,*depths,depcount;
char buf[200];
TRACE(ddraw, "(%p)->SetDisplayMode(%ld,%ld,%ld)\n",
this, width, height, depth);
- /* We hope getting the asked for depth */
- this->d.screen_depth = depth;
+ switch (_common_depth_to_pixelformat(depth,
+ &(this->d.directdraw_pixelformat),
+ &(this->d.screen_pixelformat),
+ &(this->d.pixmap_depth))) {
+ case 0:
+ sprintf(buf,"SetDisplayMode(w=%ld,h=%ld,d=%ld), unsupported depth!",width,height,depth);
+ MessageBoxA(0,buf,"WINE DirectDraw",MB_OK|MB_ICONSTOP);
+ return DDERR_UNSUPPORTEDMODE;
- depths = TSXListDepths(display,DefaultScreen(display),&depcount);
+ case 1:
+ /* No convertion */
+ this->d.pixel_convert = NULL;
+ this->d.palette_convert = NULL;
+ break;
- for (i=0;i<depcount;i++)
- if (depths[i]==depth)
+ case 2: {
+ int found = 0;
+
+ WARN(ddraw, "Warning : running in depth-convertion mode. Should run using a %ld depth for optimal performances.\n", depth);
+
+ /* Set the depth convertion routines */
+ switch (this->d.screen_pixelformat.x.dwRGBBitCount) {
+ case 16:
+ if ((this->d.screen_pixelformat.y.dwRBitMask == 0xF800) &&
+ (this->d.screen_pixelformat.z.dwGBitMask == 0x07E0) &&
+ (this->d.screen_pixelformat.xx.dwBBitMask == 0x001F)) {
+ /* 16 bpp */
+ found = 1;
+
+ this->d.pixel_convert = pixel_convert_16_to_8;
+ this->d.palette_convert = palette_convert_16_to_8;
+ } else if ((this->d.screen_pixelformat.y.dwRBitMask == 0x7C00) &&
+ (this->d.screen_pixelformat.z.dwGBitMask == 0x03E0) &&
+ (this->d.screen_pixelformat.xx.dwBBitMask == 0x001F)) {
+ /* 15 bpp */
+ found = 1;
+
+ this->d.pixel_convert = pixel_convert_16_to_8;
+ this->d.palette_convert = palette_convert_15_to_8;
+ }
+ break;
+
+ case 24:
+ /* Not handled yet :/ */
+ found = 0;
break;
- if (i==depcount) {/* not found */
- for (i=0;i<depcount;i++)
- if (depths[i]==16)
- break;
+
+ case 32:
+ if ((this->d.screen_pixelformat.y.dwRBitMask == 0xFF0000) &&
+ (this->d.screen_pixelformat.z.dwGBitMask == 0x00FF00) &&
+ (this->d.screen_pixelformat.xx.dwBBitMask == 0x0000FF)) {
+ /* 24 bpp */
+ found = 1;
- if (i==depcount) {
+ this->d.pixel_convert = pixel_convert_32_to_8;
+ this->d.palette_convert = palette_convert_24_to_8;
+ }
+ break;
+ }
+
+ if (!found) {
sprintf(buf,"SetDisplayMode(w=%ld,h=%ld,d=%ld), unsupported depth!",width,height,depth);
MessageBoxA(0,buf,"WINE DirectDraw",MB_OK|MB_ICONSTOP);
- TSXFree(depths);
return DDERR_UNSUPPORTEDMODE;
- } else {
- WARN(ddraw, "Warning : running in depth-convertion mode. Should run using a %ld depth for optimal performances.\n", depth);
- this->d.screen_depth = 16;
}
+ } break;
}
- TSXFree(depths);
this->d.width = width;
this->d.height = height;
- this->d.depth = depth;
_common_IDirectDraw_SetDisplayMode(this);
@@ -2959,43 +3087,13 @@
if (palent)
{
/* Now, if we are in 'depth conversion mode', create the screen palette */
- if (this->d.depth != this->d.screen_depth) {
- int i;
-
- switch (this->d.screen_depth) {
- case 16: {
- unsigned short *screen_palette = (unsigned short *) (*lpddpal)->screen_palents;
-
- for (i = 0; i < size; i++) {
- screen_palette[i] = (((((unsigned short) palent[i].peRed) & 0xF8) << 8) |
- ((((unsigned short) palent[i].peBlue) & 0xF8) >> 3) |
- ((((unsigned short) palent[i].peGreen) & 0xFC) << 3));
- }
- } break;
+ if (this->d.palette_convert != NULL)
+ this->d.palette_convert(palent, (*lpddpal)->screen_palents, 0, size);
- default:
- ERR(ddraw, "Memory corruption ! (depth=%ld, screen_depth=%ld)\n",this->d.depth,this->d.screen_depth);
- break;
- }
- }
-
memcpy((*lpddpal)->palents, palent, size * sizeof(PALETTEENTRY));
- } else if (this->d.depth != this->d.screen_depth) {
- int i;
-
- switch (this->d.screen_depth) {
- case 16: {
- unsigned short *screen_palette = (unsigned short *) (*lpddpal)->screen_palents;
-
- for (i = 0; i < size; i++) {
- screen_palette[i] = 0xFFFF;
- }
- } break;
-
- default:
- ERR(ddraw, "Memory corruption !\n");
- break;
- }
+ } else if (this->d.palette_convert != NULL) {
+ /* In that case, put all 0xFF */
+ memset((*lpddpal)->screen_palents, 0xFF, 256 * sizeof(int));
}
return DD_OK;
@@ -3011,7 +3109,7 @@
res = common_IDirectDraw2_CreatePalette(this,dwFlags,palent,lpddpal,lpunk,&xsize);
if (res != 0) return res;
(*lpddpal)->lpvtbl = &dga_ddpalvt;
- if (this->d.depth<=8) {
+ if (this->d.directdraw_pixelformat.x.dwRGBBitCount<=8) {
(*lpddpal)->cm = TSXCreateColormap(display,DefaultRootWindow(display),DefaultVisualOfScreen(X11DRV_GetXScreen()),AllocAll);
} else {
FIXME(ddraw,"why are we doing CreatePalette in hi/truecolor?\n");
@@ -3278,7 +3376,7 @@
return DD_OK;
}
-static HRESULT WINAPI IDirectDraw2_EnumDisplayModes(
+static HRESULT WINAPI DGA_IDirectDraw2_EnumDisplayModes(
LPDIRECTDRAW2 this,DWORD dwFlags,LPDDSURFACEDESC lpddsfd,LPVOID context,LPDDENUMMODESCALLBACK modescb
) {
DDSURFACEDESC ddsfd;
@@ -3362,6 +3460,132 @@
return DD_OK;
}
+static HRESULT WINAPI Xlib_IDirectDraw2_EnumDisplayModes(
+ LPDIRECTDRAW2 this,DWORD dwFlags,LPDDSURFACEDESC lpddsfd,LPVOID context,LPDDENUMMODESCALLBACK modescb
+) {
+ XVisualInfo *vi;
+ XPixmapFormatValues *pf;
+ XVisualInfo vt;
+ int nvisuals, npixmap, i;
+ int send_mode;
+ int has_8bpp = 0;
+ DDSURFACEDESC ddsfd;
+ static struct {
+ int w,h;
+ } modes[] = { /* some of the usual modes */
+ {512,384},
+ {640,400},
+ {640,480},
+ {800,600},
+ {1024,768},
+ {1280,1024}
+ };
+ DWORD maxWidth, maxHeight;
+
+ TRACE(ddraw,"(%p)->(0x%08lx,%p,%p,%p)\n",this,dwFlags,lpddsfd,context,modescb);
+ ddsfd.dwSize = sizeof(ddsfd);
+ ddsfd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_CAPS;
+ if (dwFlags & DDEDM_REFRESHRATES) {
+ ddsfd.dwFlags |= DDSD_REFRESHRATE;
+ ddsfd.x.dwRefreshRate = 60;
+ }
+ maxWidth = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
+ maxHeight = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
+
+ vi = TSXGetVisualInfo(display, VisualNoMask, &vt, &nvisuals);
+ pf = XListPixmapFormats(display, &npixmap);
+
+ i = 0;
+ send_mode = 0;
+ while (i < npixmap) {
+ if ((has_8bpp == 0) && (pf[i].depth == 8)) {
+ /* Special case of a 8bpp depth */
+ has_8bpp = 1;
+ send_mode = 1;
+
+ ddsfd.ddsCaps.dwCaps = DDSCAPS_PALETTE;
+ ddsfd.ddpfPixelFormat.dwSize = sizeof(ddsfd.ddpfPixelFormat);
+ ddsfd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8;
+ ddsfd.ddpfPixelFormat.dwFourCC = 0;
+ ddsfd.ddpfPixelFormat.x.dwRGBBitCount = 8;
+ ddsfd.ddpfPixelFormat.y.dwRBitMask = 0;
+ ddsfd.ddpfPixelFormat.z.dwGBitMask = 0;
+ ddsfd.ddpfPixelFormat.xx.dwBBitMask = 0;
+ ddsfd.ddpfPixelFormat.xy.dwRGBAlphaBitMask= 0;
+ } else if (pf[i].depth > 8) {
+ int j;
+
+ /* All the 'true color' depths (15, 16 and 24)
+ First, find the corresponding visual to extract the bit masks */
+ for (j = 0; j < nvisuals; j++) {
+ if (vi[j].depth == pf[i].depth) {
+ ddsfd.ddsCaps.dwCaps = 0;
+ ddsfd.ddpfPixelFormat.dwSize = sizeof(ddsfd.ddpfPixelFormat);
+ ddsfd.ddpfPixelFormat.dwFlags = DDPF_RGB;
+ ddsfd.ddpfPixelFormat.dwFourCC = 0;
+ ddsfd.ddpfPixelFormat.x.dwRGBBitCount = pf[i].bits_per_pixel;
+ ddsfd.ddpfPixelFormat.y.dwRBitMask = vi[j].red_mask;
+ ddsfd.ddpfPixelFormat.z.dwGBitMask = vi[j].green_mask;
+ ddsfd.ddpfPixelFormat.xx.dwBBitMask = vi[j].blue_mask;
+ ddsfd.ddpfPixelFormat.xy.dwRGBAlphaBitMask= 0;
+
+ send_mode = 1;
+ break;
+ }
+ }
+
+ if (j == nvisuals)
+ ERR(ddraw, "Did not find visual corresponding the the pixmap format !\n");
+ } else {
+ send_mode = 0;
+ }
+
+ if (send_mode) {
+ int mode;
+
+ if (TRACE_ON(ddraw)) {
+ TRACE(ddraw, "Enumerating with pixel format : \n");
+ _dump_pixelformat(&(ddsfd.ddpfPixelFormat));
+ }
+
+ for (mode = 0; mode < sizeof(modes)/sizeof(modes[0]); mode++) {
+ /* Do not enumerate modes we cannot handle anyway */
+ if ((modes[mode].w > maxWidth) || (modes[mode].h > maxHeight))
+ break;
+
+ ddsfd.dwWidth = modes[mode].w;
+ ddsfd.dwHeight = modes[mode].h;
+
+ /* Now, send the mode description to the application */
+ TRACE(ddraw, " - mode %4ld - %4ld\n", ddsfd.dwWidth, ddsfd.dwHeight);
+ if (!modescb(&ddsfd, context))
+ goto exit_enum;
+ }
+
+ if (!(dwFlags & DDEDM_STANDARDVGAMODES)) {
+ /* modeX is not standard VGA */
+ ddsfd.dwWidth = 320;
+ ddsfd.dwHeight = 200;
+ if (!modescb(&ddsfd, context))
+ goto exit_enum;
+ }
+ }
+
+ /* Hack to always enumerate a 8bpp depth */
+ i++;
+ if ((i == npixmap) && (has_8bpp == 0)) {
+ i--;
+ pf[i].depth = 8;
+ }
+ }
+
+ exit_enum:
+ TSXFree(vi);
+ TSXFree(pf);
+
+ return DD_OK;
+}
+
static HRESULT WINAPI DGA_IDirectDraw2_GetDisplayMode(
LPDIRECTDRAW2 this,LPDDSURFACEDESC lpddsfd
) {
@@ -3370,11 +3594,11 @@
lpddsfd->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
lpddsfd->dwHeight = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
lpddsfd->dwWidth = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
- lpddsfd->lPitch = this->e.dga.fb_width*this->d.depth/8;
+ lpddsfd->lPitch = this->e.dga.fb_width*this->d.directdraw_pixelformat.x.dwRGBBitCount/8;
lpddsfd->dwBackBufferCount = 1;
lpddsfd->x.dwRefreshRate = 60;
lpddsfd->ddsCaps.dwCaps = DDSCAPS_PALETTE;
- _getpixelformat(this,&(lpddsfd->ddpfPixelFormat));
+ lpddsfd->ddpfPixelFormat = this->d.directdraw_pixelformat;
return DD_OK;
#else /* defined(HAVE_LIBXXF86DGA) */
return E_UNEXPECTED;
@@ -3388,13 +3612,11 @@
lpddsfd->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
lpddsfd->dwHeight = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
lpddsfd->dwWidth = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
- /* POOLE FIXME: Xlib */
- lpddsfd->lPitch = this->e.dga.fb_width*this->d.depth/8;
- /* END FIXME: Xlib */
+ lpddsfd->lPitch = lpddsfd->dwWidth * this->d.directdraw_pixelformat.x.dwRGBBitCount/8;
lpddsfd->dwBackBufferCount = 1;
lpddsfd->x.dwRefreshRate = 60;
lpddsfd->ddsCaps.dwCaps = DDSCAPS_PALETTE;
- _getpixelformat(this,&(lpddsfd->ddpfPixelFormat));
+ lpddsfd->ddpfPixelFormat = this->d.directdraw_pixelformat;
return DD_OK;
}
@@ -3471,7 +3693,7 @@
XCAST(CreatePalette)DGA_IDirectDraw2_CreatePalette,
XCAST(CreateSurface)DGA_IDirectDraw2_CreateSurface,
XCAST(DuplicateSurface)IDirectDraw2_DuplicateSurface,
- XCAST(EnumDisplayModes)IDirectDraw2_EnumDisplayModes,
+ XCAST(EnumDisplayModes)DGA_IDirectDraw2_EnumDisplayModes,
XCAST(EnumSurfaces)IDirectDraw2_EnumSurfaces,
XCAST(FlipToGDISurface)IDirectDraw2_FlipToGDISurface,
XCAST(GetCaps)DGA_IDirectDraw2_GetCaps,
@@ -3497,7 +3719,7 @@
XCAST(CreatePalette)Xlib_IDirectDraw2_CreatePalette,
XCAST(CreateSurface)Xlib_IDirectDraw2_CreateSurface,
XCAST(DuplicateSurface)IDirectDraw2_DuplicateSurface,
- XCAST(EnumDisplayModes)IDirectDraw2_EnumDisplayModes,
+ XCAST(EnumDisplayModes)Xlib_IDirectDraw2_EnumDisplayModes,
XCAST(EnumSurfaces)IDirectDraw2_EnumSurfaces,
XCAST(FlipToGDISurface)IDirectDraw2_FlipToGDISurface,
XCAST(GetCaps)Xlib_IDirectDraw2_GetCaps,
@@ -3565,7 +3787,7 @@
DGA_IDirectDraw2_CreatePalette,
DGA_IDirectDraw2_CreateSurface,
IDirectDraw2_DuplicateSurface,
- IDirectDraw2_EnumDisplayModes,
+ DGA_IDirectDraw2_EnumDisplayModes,
IDirectDraw2_EnumSurfaces,
IDirectDraw2_FlipToGDISurface,
DGA_IDirectDraw2_GetCaps,
@@ -3592,7 +3814,7 @@
Xlib_IDirectDraw2_CreatePalette,
Xlib_IDirectDraw2_CreateSurface,
IDirectDraw2_DuplicateSurface,
- IDirectDraw2_EnumDisplayModes,
+ Xlib_IDirectDraw2_EnumDisplayModes,
IDirectDraw2_EnumSurfaces,
IDirectDraw2_FlipToGDISurface,
Xlib_IDirectDraw2_GetCaps,
@@ -3659,7 +3881,7 @@
XCAST(CreatePalette)DGA_IDirectDraw2_CreatePalette,
XCAST(CreateSurface)DGA_IDirectDraw2_CreateSurface,
XCAST(DuplicateSurface)IDirectDraw2_DuplicateSurface,
- XCAST(EnumDisplayModes)IDirectDraw2_EnumDisplayModes,
+ XCAST(EnumDisplayModes)DGA_IDirectDraw2_EnumDisplayModes,
XCAST(EnumSurfaces)IDirectDraw2_EnumSurfaces,
XCAST(FlipToGDISurface)IDirectDraw2_FlipToGDISurface,
XCAST(GetCaps)DGA_IDirectDraw2_GetCaps,
@@ -3690,7 +3912,7 @@
XCAST(CreatePalette)Xlib_IDirectDraw2_CreatePalette,
XCAST(CreateSurface)Xlib_IDirectDraw2_CreateSurface,
XCAST(DuplicateSurface)IDirectDraw2_DuplicateSurface,
- XCAST(EnumDisplayModes)IDirectDraw2_EnumDisplayModes,
+ XCAST(EnumDisplayModes)Xlib_IDirectDraw2_EnumDisplayModes,
XCAST(EnumSurfaces)IDirectDraw2_EnumSurfaces,
XCAST(FlipToGDISurface)IDirectDraw2_FlipToGDISurface,
XCAST(GetCaps)Xlib_IDirectDraw2_GetCaps,
@@ -3782,6 +4004,7 @@
int memsize,banksize,width,major,minor,flags,height;
char *addr;
int fd;
+ int depth;
/* Must be able to access /dev/mem for DGA extensions to work, root is not neccessary. --stephenc */
if ((fd = open("/dev/mem", O_RDWR)) != -1)
@@ -3824,8 +4047,8 @@
#endif
/* just assume the default depth is the DGA depth too */
- (*lplpDD)->d.screen_depth = DefaultDepthOfScreen(X11DRV_GetXScreen());
- (*lplpDD)->d.depth = DefaultDepthOfScreen(X11DRV_GetXScreen());
+ depth = DefaultDepthOfScreen(X11DRV_GetXScreen());
+ _common_depth_to_pixelformat(depth, &((*lplpDD)->d.directdraw_pixelformat), &((*lplpDD)->d.screen_pixelformat), NULL);
#ifdef RESTORE_SIGNALS
SIGNAL_InitHandlers();
#endif
@@ -3858,6 +4081,7 @@
}
HRESULT WINAPI Xlib_DirectDrawCreate( LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnkOuter) {
+ int depth;
*lplpDD = (LPDIRECTDRAW)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDraw));
(*lplpDD)->lpvtbl = &xlib_ddvt;
@@ -3865,8 +4089,8 @@
(*lplpDD)->d.drawable = 0; /* in SetDisplayMode */
/* At DirectDraw creation, the depth is the default depth */
- (*lplpDD)->d.depth = DefaultDepthOfScreen(X11DRV_GetXScreen());
- (*lplpDD)->d.screen_depth = DefaultDepthOfScreen(X11DRV_GetXScreen());
+ depth = DefaultDepthOfScreen(X11DRV_GetXScreen());
+ _common_depth_to_pixelformat(depth, &((*lplpDD)->d.directdraw_pixelformat), &((*lplpDD)->d.screen_pixelformat), NULL);
(*lplpDD)->d.height = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
(*lplpDD)->d.width = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
diff --git a/include/ddraw.h b/include/ddraw.h
index 1115e25..5b22d7a 100644
--- a/include/ddraw.h
+++ b/include/ddraw.h
@@ -912,8 +912,11 @@
} *LPDIRECTDRAW_VTABLE,IDirectDraw_VTable;
struct _common_directdrawdata {
- DWORD screen_depth;
- DWORD depth; /* SetDisplayMode */
+ DDPIXELFORMAT directdraw_pixelformat;
+ DDPIXELFORMAT screen_pixelformat;
+ int pixmap_depth;
+ void (*pixel_convert)(void *src, void *dst, DWORD width, DWORD height, LONG pitch, LPDIRECTDRAWPALETTE palette);
+ void (*palette_convert)(LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count);
DWORD height,width; /* SetDisplayMode */
HWND mainWindow; /* SetCooperativeLevel */