Truncate dest blit rectangle down to surface size.
[wine] / dlls / ddraw / dsurface / main.c
1 /*              DirectDrawSurface base implementation
2  *
3  * Copyright 1997-2000 Marcus Meissner
4  * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
5  */
6 #include "config.h"
7 #include "winerror.h"
8
9
10 #include <unistd.h>
11 #include <assert.h>
12 #include <fcntl.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <stdio.h>
16
17 #include "debugtools.h"
18 #include "bitmap.h"
19 #include "ddraw_private.h"
20
21 DEFAULT_DEBUG_CHANNEL(ddraw);
22
23 /******************************************************************************
24  *              IDirectDrawSurface methods
25  *
26  * Since DDS3 and DDS2 are supersets of DDS, we implement DDS3 and let
27  * DDS and DDS2 use those functions. (Function calls did not change (except
28  * using different DirectDrawSurfaceX version), just added flags and functions)
29  */
30
31 HRESULT WINAPI IDirectDrawSurface4Impl_Lock(
32     LPDIRECTDRAWSURFACE4 iface,LPRECT lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE hnd
33 ) {
34     ICOM_THIS(IDirectDrawSurface4Impl,iface);
35
36     TRACE("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
37         This,lprect,lpddsd,flags,(DWORD)hnd);
38
39     /* DO NOT AddRef the surface! Lock/Unlock must not come in matched pairs
40      * -Marcus Meissner 20000509
41      */
42     if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
43         WARN("(%p)->Lock(%p,%p,%08lx,%08lx)\n",
44                  This,lprect,lpddsd,flags,(DWORD)hnd);
45
46     /* First, copy the Surface description */
47     *lpddsd = This->s.surface_desc;
48     TRACE("locked surface: height=%ld, width=%ld, pitch=%ld\n",
49           lpddsd->dwHeight,lpddsd->dwWidth,lpddsd->lPitch);
50
51     /* If asked only for a part, change the surface pointer */
52     if (lprect) {
53         TRACE(" lprect: %dx%d-%dx%d\n",
54                 lprect->top,lprect->left,lprect->bottom,lprect->right
55         );
56         if ((lprect->top < 0) ||
57             (lprect->left < 0) ||
58             (lprect->bottom < 0) ||
59             (lprect->right < 0)) {
60           ERR(" Negative values in LPRECT !!!\n");
61           return DDERR_INVALIDPARAMS;
62        }
63        
64         lpddsd->u1.lpSurface = (LPVOID) ((char *) This->s.surface_desc.u1.lpSurface +
65                 (lprect->top*This->s.surface_desc.lPitch) +
66                 lprect->left*GET_BPP(This->s.surface_desc));
67     } else {
68         assert(This->s.surface_desc.u1.lpSurface);
69     }
70     return DD_OK;
71 }
72
73 HRESULT WINAPI IDirectDrawSurface4Impl_Unlock(
74     LPDIRECTDRAWSURFACE4 iface,LPVOID surface
75 ) {
76     ICOM_THIS(IDirectDrawSurface4Impl,iface);
77
78     /* DO NOT Release the surface! Lock/Unlock MUST NOT come in matched pairs
79      * Marcus Meissner 20000509
80      */
81     TRACE("(%p)->Unlock(%p)\n",This,surface);
82     return DD_OK;
83 }
84
85 IDirectDrawSurface4Impl* _common_find_flipto(
86     IDirectDrawSurface4Impl* This,IDirectDrawSurface4Impl* flipto
87 ) {
88     int i,j,flipable=0;
89     struct _surface_chain       *chain = This->s.chain;
90
91     if (!chain) {
92         ERR("No flip chain? -> returning This.\n");
93         return This;
94     }
95
96     /* if there was no override flipto, look for current backbuffer */
97     if (!flipto) {
98         /* walk the flip chain looking for backbuffer */
99         for (i=0;i<chain->nrofsurfaces;i++) {
100             if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_FLIP)
101                 flipable++;
102             if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_BACKBUFFER)
103                 flipto = chain->surfaces[i];
104         }
105         /* sanity checks ... */
106         if (!flipto) {
107             if (flipable>1) {
108                 for (i=0;i<chain->nrofsurfaces;i++)
109                     if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_FRONTBUFFER)
110                         break;
111                 if (i==chain->nrofsurfaces) {
112                     /* we do not have a frontbuffer either */
113                     for (i=0;i<chain->nrofsurfaces;i++)
114                         if (SDDSCAPS(chain->surfaces[i]) & DDSCAPS_FLIP) {
115                             SDDSCAPS(chain->surfaces[i])|=DDSCAPS_FRONTBUFFER;
116                             break;
117                         }
118                     for (j=i+1;j<i+chain->nrofsurfaces+1;j++) {
119                         int k = j % chain->nrofsurfaces;
120                         if (SDDSCAPS(chain->surfaces[k]) & DDSCAPS_FLIP) {
121                             SDDSCAPS(chain->surfaces[k])|=DDSCAPS_BACKBUFFER;
122                             flipto = chain->surfaces[k];
123                             break;
124                         }
125                     }
126                 }
127             }
128             if (!flipto)
129                 flipto = This;
130         }
131         TRACE("flipping to %p\n",flipto);
132     }
133     return flipto;
134 }
135
136 static HRESULT _Blt_ColorFill(
137     LPBYTE buf, int width, int height, int bpp, LONG lPitch, DWORD color
138 ) {
139     int x, y;
140     LPBYTE first;
141
142     /* Do first row */
143
144 #define COLORFILL_ROW(type) { \
145     type *d = (type *) buf; \
146     for (x = 0; x < width; x++) \
147         d[x] = (type) color; \
148     break; \
149 }
150
151     switch(bpp) {
152     case 1: COLORFILL_ROW(BYTE)
153     case 2: COLORFILL_ROW(WORD)
154     case 4: COLORFILL_ROW(DWORD)
155     default:
156         FIXME("Color fill not implemented for bpp %d!\n", bpp*8);
157         return DDERR_UNSUPPORTED;
158     }
159
160 #undef COLORFILL_ROW
161
162     /* Now copy first row */
163     first = buf;
164     for (y = 1; y < height; y++) {
165         buf += lPitch;
166         memcpy(buf, first, width * bpp);
167     }
168     return DD_OK;
169 }
170
171 HRESULT WINAPI IDirectDrawSurface4Impl_Blt(
172     LPDIRECTDRAWSURFACE4 iface,LPRECT rdst,LPDIRECTDRAWSURFACE4 src,LPRECT rsrc,
173     DWORD dwFlags,LPDDBLTFX lpbltfx
174 ) {
175     ICOM_THIS(IDirectDrawSurface4Impl,iface);
176     RECT                xdst,xsrc;
177     DDSURFACEDESC       ddesc,sdesc;
178     HRESULT             ret = DD_OK;
179     int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
180     int x, y;
181     LPBYTE dbuf, sbuf;
182
183     TRACE("(%p)->(%p,%p,%p,%08lx,%p)\n", This,rdst,src,rsrc,dwFlags,lpbltfx);
184
185     if (src) IDirectDrawSurface4_Lock(src, NULL, &sdesc, 0, 0);
186     IDirectDrawSurface4_Lock(iface,NULL,&ddesc,0,0);
187
188     if (TRACE_ON(ddraw)) {
189         if (rdst) TRACE("\tdestrect :%dx%d-%dx%d\n",rdst->left,rdst->top,rdst->right,rdst->bottom);
190         if (rsrc) TRACE("\tsrcrect  :%dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
191         TRACE("\tflags: ");
192         _dump_DDBLT(dwFlags);
193         if (dwFlags & DDBLT_DDFX) {
194             TRACE("\tblitfx: ");
195             _dump_DDBLTFX(lpbltfx->dwDDFX);
196         }
197     }
198
199     if (rdst) {
200         if ((rdst->top < 0) ||
201             (rdst->left < 0) ||
202             (rdst->bottom < 0) ||
203             (rdst->right < 0)) {
204           ERR(" Negative values in LPRECT !!!\n");
205           goto release;
206         }
207         memcpy(&xdst,rdst,sizeof(xdst));
208     } else {
209         xdst.top        = 0;
210         xdst.bottom     = ddesc.dwHeight;
211         xdst.left       = 0;
212         xdst.right      = ddesc.dwWidth;
213     }
214
215     if (rsrc) {
216         if ((rsrc->top < 0) ||
217             (rsrc->left < 0) ||
218             (rsrc->bottom < 0) ||
219             (rsrc->right < 0)) {
220           ERR(" Negative values in LPRECT !!!\n");
221           goto release;
222         }
223         memcpy(&xsrc,rsrc,sizeof(xsrc));
224     } else {
225         if (src) {
226             xsrc.top    = 0;
227             xsrc.bottom = sdesc.dwHeight;
228             xsrc.left   = 0;
229             xsrc.right  = sdesc.dwWidth;
230         } else {
231             memset(&xsrc,0,sizeof(xsrc));
232         }
233     }
234     if (src) assert((xsrc.bottom-xsrc.top) <= sdesc.dwHeight);
235
236     /* truncate dst rect to dest surface. */
237     if ((xdst.bottom-xdst.top) > ddesc.dwHeight)
238         xdst.bottom = xdst.top+ddesc.dwHeight;
239     if ((xdst.right-xdst.left) > ddesc.dwWidth)
240         xdst.right = xdst.left+ddesc.dwWidth;
241
242     bpp = GET_BPP(ddesc);
243     srcheight = xsrc.bottom - xsrc.top;
244     srcwidth = xsrc.right - xsrc.left;
245     dstheight = xdst.bottom - xdst.top;
246     dstwidth = xdst.right - xdst.left;
247     width = (xdst.right - xdst.left) * bpp;
248
249     assert(width <= ddesc.lPitch);
250
251     dbuf = (BYTE*)ddesc.u1.lpSurface+(xdst.top*ddesc.lPitch)+(xdst.left*bpp);
252
253     dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC);/* FIXME: can't handle right now */
254
255     /* First, all the 'source-less' blits */
256     if (dwFlags & DDBLT_COLORFILL) {
257         ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp,
258                              ddesc.lPitch, lpbltfx->u4.dwFillColor);
259         dwFlags &= ~DDBLT_COLORFILL;
260     }
261
262     if (dwFlags & DDBLT_DEPTHFILL)
263         FIXME("DDBLT_DEPTHFILL needs to be implemented!\n");
264     if (dwFlags & DDBLT_ROP) {
265         /* Catch some degenerate cases here */
266         switch(lpbltfx->dwROP) {
267         case BLACKNESS:
268             ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,ddesc.lPitch,0);
269             break;
270         case 0xAA0029: /* No-op */
271             break;
272         case WHITENESS:
273             ret = _Blt_ColorFill(dbuf,dstwidth,dstheight,bpp,ddesc.lPitch,~0);
274             break;
275         default: 
276             FIXME("Unsupported raster op: %08lx  Pattern: %p\n", lpbltfx->dwROP, lpbltfx->u4.lpDDSPattern);
277             goto error;
278         }
279         dwFlags &= ~DDBLT_ROP;
280     }
281     if (dwFlags & DDBLT_DDROPS) {
282         FIXME("\tDdraw Raster Ops: %08lx  Pattern: %p\n", lpbltfx->dwDDROP, lpbltfx->u4.lpDDSPattern);
283     }
284     /* Now the 'with source' blits */
285     if (src) {
286         LPBYTE sbase;
287         int sx, xinc, sy, yinc;
288
289         if (!dstwidth || !dstheight) /* hmm... stupid program ? */
290             goto release;
291         sbase = (BYTE*)sdesc.u1.lpSurface+(xsrc.top*sdesc.lPitch)+xsrc.left*bpp;
292         xinc = (srcwidth << 16) / dstwidth;
293         yinc = (srcheight << 16) / dstheight;
294
295         if (!dwFlags) {
296             /* No effects, we can cheat here */
297             if (dstwidth == srcwidth) {
298                 if (dstheight == srcheight) {
299                     /* No stretching in either direction. This needs to be as
300                      * fast as possible */
301                     sbuf = sbase;
302                     for (y = 0; y < dstheight; y++) {
303                         memcpy(dbuf, sbuf, width);
304                         sbuf += sdesc.lPitch;
305                         dbuf += ddesc.lPitch;
306                     }
307                 } else {
308                     /* Stretching in Y direction only */
309                     for (y = sy = 0; y < dstheight; y++, sy += yinc) {
310                         sbuf = sbase + (sy >> 16) * sdesc.lPitch;
311                         memcpy(dbuf, sbuf, width);
312                         dbuf += ddesc.lPitch;
313                     }
314                 }
315             } else {
316                 /* Stretching in X direction */
317                 int last_sy = -1;
318                 for (y = sy = 0; y < dstheight; y++, sy += yinc) {
319                     sbuf = sbase + (sy >> 16) * sdesc.lPitch;
320
321                     if ((sy >> 16) == (last_sy >> 16)) {
322                         /* this sourcerow is the same as last sourcerow -
323                          * copy already stretched row
324                          */
325                         memcpy(dbuf, dbuf - ddesc.lPitch, width);
326                     } else {
327 #define STRETCH_ROW(type) { \
328                     type *s = (type *) sbuf, *d = (type *) dbuf; \
329                     for (x = sx = 0; x < dstwidth; x++, sx += xinc) \
330                     d[x] = s[sx >> 16]; \
331                     break; }
332
333                     switch(bpp) {
334                     case 1: STRETCH_ROW(BYTE)
335                     case 2: STRETCH_ROW(WORD)
336                     case 4: STRETCH_ROW(DWORD)
337                     case 3: {
338                         LPBYTE s,d = dbuf;
339                         for (x = sx = 0; x < dstwidth; x++, sx+= xinc) {
340                             DWORD pixel;
341
342                             s = sbuf+3*(sx>>16);
343                             pixel = (s[0]<<16)|(s[1]<<8)|s[2];
344                             d[0] = (pixel>>16)&0xff;
345                             d[1] = (pixel>> 8)&0xff;
346                             d[2] = (pixel    )&0xff;
347                             d+=3;
348                         }
349                         break;
350                     }
351                     default:
352                         FIXME("Stretched blit not implemented for bpp %d!\n", bpp*8);
353                         ret = DDERR_UNSUPPORTED;
354                         goto error;
355                     }
356 #undef STRETCH_ROW
357                     }
358                     dbuf += ddesc.lPitch;
359                     last_sy = sy;
360                 }
361             }
362         } else if (dwFlags & (DDBLT_KEYSRC | DDBLT_KEYDEST)) {
363             DWORD keylow, keyhigh;
364
365             if (dwFlags & DDBLT_KEYSRC) {
366                 keylow  = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue;
367                 keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue;
368             } else {
369                 /* I'm not sure if this is correct */
370                 FIXME("DDBLT_KEYDEST not fully supported yet.\n");
371                 keylow  = ddesc.ddckCKDestBlt.dwColorSpaceLowValue;
372                 keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue;
373             }
374
375
376             for (y = sy = 0; y < dstheight; y++, sy += yinc) {
377                 sbuf = sbase + (sy >> 16) * sdesc.lPitch;
378
379 #define COPYROW_COLORKEY(type) { \
380                 type *s = (type *) sbuf, *d = (type *) dbuf, tmp; \
381                 for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
382                     tmp = s[sx >> 16]; \
383                     if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
384                 } \
385                 break; }
386
387                 switch (bpp) {
388                 case 1: COPYROW_COLORKEY(BYTE)
389                 case 2: COPYROW_COLORKEY(WORD)
390                 case 4: COPYROW_COLORKEY(DWORD)
391                 default:
392                     FIXME("%s color-keyed blit not implemented for bpp %d!\n",
393                     (dwFlags & DDBLT_KEYSRC) ? "Source" : "Destination", bpp*8);
394                     ret = DDERR_UNSUPPORTED;
395                     goto error;
396                 }
397                 dbuf += ddesc.lPitch;
398             }
399 #undef COPYROW_COLORKEY
400             dwFlags &= ~(DDBLT_KEYSRC | DDBLT_KEYDEST);
401         }
402     }
403
404 error:
405     if (dwFlags && FIXME_ON(ddraw)) {
406         FIXME("\tUnsupported flags: ");
407         _dump_DDBLT(dwFlags);
408     }
409
410 release:
411     IDirectDrawSurface4_Unlock(iface,ddesc.u1.lpSurface);
412     if (src) IDirectDrawSurface4_Unlock(src,sdesc.u1.lpSurface);
413     return DD_OK;
414 }
415
416 HRESULT WINAPI IDirectDrawSurface4Impl_BltFast(
417     LPDIRECTDRAWSURFACE4 iface,DWORD dstx,DWORD dsty,LPDIRECTDRAWSURFACE4 src,
418     LPRECT rsrc,DWORD trans
419 ) {
420     ICOM_THIS(IDirectDrawSurface4Impl,iface);
421     int                 bpp, w, h, x, y;
422     DDSURFACEDESC       ddesc,sdesc;
423     HRESULT             ret = DD_OK;
424     LPBYTE              sbuf, dbuf;
425     RECT                rsrc2;
426
427
428     if (TRACE_ON(ddraw)) {
429         FIXME("(%p)->(%ld,%ld,%p,%p,%08lx)\n",
430                 This,dstx,dsty,src,rsrc,trans
431         );
432         FIXME(" trans:");
433         if (FIXME_ON(ddraw))
434           _dump_DDBLTFAST(trans);
435         if (rsrc)
436           FIXME("\tsrcrect: %dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
437         else
438           FIXME(" srcrect: NULL\n");
439     }
440     
441     /* We need to lock the surfaces, or we won't get refreshes when done. */
442     IDirectDrawSurface4_Lock(src, NULL,&sdesc,DDLOCK_READONLY, 0);
443     IDirectDrawSurface4_Lock(iface,NULL,&ddesc,DDLOCK_WRITEONLY,0);
444
445    if (!rsrc) {
446            WARN("rsrc is NULL!\n");
447            rsrc = &rsrc2;
448            rsrc->left = rsrc->top = 0;
449            rsrc->right = sdesc.dwWidth;
450            rsrc->bottom = sdesc.dwHeight;
451    }
452
453     bpp = GET_BPP(This->s.surface_desc);
454     sbuf = (BYTE *)sdesc.u1.lpSurface+(rsrc->top*sdesc.lPitch)+rsrc->left*bpp;
455     dbuf = (BYTE *)ddesc.u1.lpSurface+(dsty*ddesc.lPitch)+dstx* bpp;
456
457
458     h=rsrc->bottom-rsrc->top;
459     if (h>ddesc.dwHeight-dsty) h=ddesc.dwHeight-dsty;
460     if (h>sdesc.dwHeight-rsrc->top) h=sdesc.dwHeight-rsrc->top;
461     if (h<0) h=0;
462
463     w=rsrc->right-rsrc->left;
464     if (w>ddesc.dwWidth-dstx) w=ddesc.dwWidth-dstx;
465     if (w>sdesc.dwWidth-rsrc->left) w=sdesc.dwWidth-rsrc->left;
466     if (w<0) w=0;
467
468     if (trans & (DDBLTFAST_SRCCOLORKEY | DDBLTFAST_DESTCOLORKEY)) {
469         DWORD keylow, keyhigh;
470         if (trans & DDBLTFAST_SRCCOLORKEY) {
471             keylow  = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue;
472             keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue;
473         } else {
474             /* I'm not sure if this is correct */
475             FIXME("DDBLTFAST_DESTCOLORKEY not fully supported yet.\n");
476             keylow  = ddesc.ddckCKDestBlt.dwColorSpaceLowValue;
477             keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue;
478         }
479
480 #define COPYBOX_COLORKEY(type) { \
481     type *d = (type *)dbuf, *s = (type *)sbuf, tmp; \
482     s = (type *) ((BYTE *) sdesc.u1.lpSurface + (rsrc->top * sdesc.lPitch) + rsrc->left * bpp); \
483     d = (type *) ((BYTE *) ddesc.u1.lpSurface + (dsty * ddesc.lPitch) + dstx * bpp); \
484     for (y = 0; y < h; y++) { \
485         for (x = 0; x < w; x++) { \
486             tmp = s[x]; \
487             if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
488         } \
489         (LPBYTE)s += sdesc.lPitch; \
490         (LPBYTE)d += ddesc.lPitch; \
491     } \
492     break; \
493 }
494
495         switch (bpp) {
496         case 1: COPYBOX_COLORKEY(BYTE)
497         case 2: COPYBOX_COLORKEY(WORD)
498         case 4: COPYBOX_COLORKEY(DWORD)
499         default:
500             FIXME("Source color key blitting not supported for bpp %d\n",bpp*8);
501             ret = DDERR_UNSUPPORTED;
502             goto error;
503         }
504 #undef COPYBOX_COLORKEY
505     } else {
506         int width = w * bpp;
507
508         for (y = 0; y < h; y++) {
509             memcpy(dbuf, sbuf, width);
510             sbuf += sdesc.lPitch;
511             dbuf += ddesc.lPitch;
512         }
513     }
514 error:
515     IDirectDrawSurface4_Unlock(iface,ddesc.u1.lpSurface);
516     IDirectDrawSurface4_Unlock(src,sdesc.u1.lpSurface);
517     return ret;
518 }
519
520 HRESULT WINAPI IDirectDrawSurface4Impl_BltBatch(
521     LPDIRECTDRAWSURFACE4 iface,LPDDBLTBATCH ddbltbatch,DWORD x,DWORD y
522 ) {
523     ICOM_THIS(IDirectDrawSurface4Impl,iface);
524     FIXME("(%p)->BltBatch(%p,%08lx,%08lx),stub!\n",This,ddbltbatch,x,y);
525     return DD_OK;
526 }
527
528 HRESULT WINAPI IDirectDrawSurface4Impl_GetCaps(
529     LPDIRECTDRAWSURFACE4 iface,LPDDSCAPS caps
530 ) {
531     ICOM_THIS(IDirectDrawSurface4Impl,iface);
532     TRACE("(%p)->GetCaps(%p)\n",This,caps);
533     caps->dwCaps = DDSCAPS_PALETTE; /* probably more */
534     return DD_OK;
535 }
536
537 HRESULT WINAPI IDirectDrawSurface4Impl_GetSurfaceDesc(
538     LPDIRECTDRAWSURFACE4 iface,LPDDSURFACEDESC ddsd
539 ) { 
540     ICOM_THIS(IDirectDrawSurface4Impl,iface);
541     TRACE("(%p)->GetSurfaceDesc(%p)\n", This,ddsd);
542   
543     /* Simply copy the surface description stored in the object */
544     *ddsd = This->s.surface_desc;
545   
546     if (TRACE_ON(ddraw)) { _dump_surface_desc(ddsd); }
547
548     return DD_OK;
549 }
550
551 ULONG WINAPI IDirectDrawSurface4Impl_AddRef(LPDIRECTDRAWSURFACE4 iface) {
552     ICOM_THIS(IDirectDrawSurface4Impl,iface);
553     TRACE("(%p)->() incrementing from %lu.\n", This, This->ref );
554     return ++(This->ref);
555 }
556
557
558 HRESULT WINAPI IDirectDrawSurface4Impl_GetAttachedSurface(
559     LPDIRECTDRAWSURFACE4 iface,LPDDSCAPS lpddsd,LPDIRECTDRAWSURFACE4 *lpdsf
560 ) {
561     ICOM_THIS(IDirectDrawSurface4Impl,iface);
562     int i,found = 0,xstart;
563     struct _surface_chain       *chain;
564
565     TRACE("(%p)->GetAttachedSurface(%p,%p)\n", This, lpddsd, lpdsf);
566     if (TRACE_ON(ddraw)) {
567         TRACE(" caps ");_dump_DDSCAPS((void *) &(lpddsd->dwCaps));
568         DPRINTF("\n");
569     }
570     chain = This->s.chain;
571     if (!chain)
572         return DDERR_NOTFOUND;
573
574     for (i=0;i<chain->nrofsurfaces;i++)
575         if (chain->surfaces[i] == This)
576             break;
577
578     xstart = i;
579     for (i=0;i<chain->nrofsurfaces;i++) {
580         if ((SDDSCAPS(chain->surfaces[(xstart+i)%chain->nrofsurfaces])&lpddsd->dwCaps) == lpddsd->dwCaps) {
581 #if 0
582             if (found) /* may not find the same caps twice, (doc) */
583                 return DDERR_INVALIDPARAMS;/*FIXME: correct? */
584 #endif
585             found = (i+1)+xstart;
586         }
587     }
588     if (!found)
589         return DDERR_NOTFOUND;
590     *lpdsf = (LPDIRECTDRAWSURFACE4)chain->surfaces[found-1-xstart];
591
592     /* For EverQuest testing */
593     IDirectDrawSurface4_AddRef(*lpdsf);
594     
595     TRACE("found %p\n",*lpdsf);
596     return DD_OK;
597 }
598
599 HRESULT WINAPI IDirectDrawSurface4Impl_Initialize(
600     LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAW ddraw,LPDDSURFACEDESC lpdsfd
601 ) {
602     ICOM_THIS(IDirectDrawSurface4Impl,iface);
603     TRACE("(%p)->(%p, %p)\n",This,ddraw,lpdsfd);
604
605     return DDERR_ALREADYINITIALIZED;
606 }
607
608 HRESULT WINAPI IDirectDrawSurface4Impl_GetPixelFormat(
609     LPDIRECTDRAWSURFACE4 iface,LPDDPIXELFORMAT pf
610 ) {
611     ICOM_THIS(IDirectDrawSurface4Impl,iface);
612     TRACE("(%p)->(%p)\n",This,pf);
613
614     *pf = This->s.surface_desc.ddpfPixelFormat;
615     if (TRACE_ON(ddraw)) { _dump_pixelformat(pf); DPRINTF("\n"); }
616     return DD_OK;
617 }
618
619 HRESULT WINAPI IDirectDrawSurface4Impl_GetBltStatus(LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags) {
620     ICOM_THIS(IDirectDrawSurface4Impl,iface);
621     FIXME("(%p)->(0x%08lx),stub!\n",This,dwFlags);
622     return DD_OK;
623 }
624
625 HRESULT WINAPI IDirectDrawSurface4Impl_GetOverlayPosition(
626     LPDIRECTDRAWSURFACE4 iface,LPLONG x1,LPLONG x2
627 ) {
628     ICOM_THIS(IDirectDrawSurface4Impl,iface);
629     FIXME("(%p)->(%p,%p),stub!\n",This,x1,x2);
630     return DD_OK;
631 }
632
633 HRESULT WINAPI IDirectDrawSurface4Impl_SetClipper(
634     LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWCLIPPER lpClipper
635 ) {
636     ICOM_THIS(IDirectDrawSurface4Impl,iface);
637     TRACE("(%p)->(%p)!\n",This,lpClipper);
638
639     if (This->s.lpClipper) IDirectDrawClipper_Release( This->s.lpClipper );
640     This->s.lpClipper = lpClipper;
641     if (lpClipper) IDirectDrawClipper_AddRef( lpClipper );
642     return DD_OK;
643 }
644
645 HRESULT WINAPI IDirectDrawSurface4Impl_AddAttachedSurface(
646     LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 surf
647 ) {
648     ICOM_THIS(IDirectDrawSurface4Impl,iface);
649     IDirectDrawSurface4Impl*isurf = (IDirectDrawSurface4Impl*)surf;
650     int i;
651     struct _surface_chain *chain;
652
653     FIXME("(%p)->(%p)\n",This,surf);
654     chain = This->s.chain;
655
656     /* IDirectDrawSurface4_AddRef(surf); */
657     
658     if (chain) {
659         for (i=0;i<chain->nrofsurfaces;i++)
660             if (chain->surfaces[i] == isurf)
661                 FIXME("attaching already attached surface %p to %p!\n",iface,isurf);
662     } else {
663         chain = HeapAlloc(GetProcessHeap(),0,sizeof(*chain));
664         chain->nrofsurfaces = 1;
665         chain->surfaces = HeapAlloc(GetProcessHeap(),0,sizeof(chain->surfaces[0]));
666         chain->surfaces[0] = This;
667         This->s.chain = chain;
668     }
669
670     if (chain->surfaces)
671         chain->surfaces = HeapReAlloc(
672             GetProcessHeap(),
673             0,
674             chain->surfaces,
675             sizeof(chain->surfaces[0])*(chain->nrofsurfaces+1)
676         );
677     else
678         chain->surfaces = HeapAlloc(GetProcessHeap(),0,sizeof(chain->surfaces[0]));
679     isurf->s.chain = chain;
680     chain->surfaces[chain->nrofsurfaces++] = isurf;
681     return DD_OK;
682 }
683
684 HRESULT WINAPI IDirectDrawSurface4Impl_GetDC(LPDIRECTDRAWSURFACE4 iface,HDC* lphdc) {
685     ICOM_THIS(IDirectDrawSurface4Impl,iface);
686     DDSURFACEDESC desc;
687     BITMAPINFO *b_info;
688     UINT usage;
689     HDC ddc;
690
691     TRACE("(%p)->GetDC(%p)\n",This,lphdc);
692
693     /* Creates a DIB Section of the same size / format as the surface */
694     IDirectDrawSurface4_Lock(iface,NULL,&desc,0,0);
695
696     if (This->s.hdc == 0) {
697         switch (desc.ddpfPixelFormat.u.dwRGBBitCount) {
698         case 16:
699         case 32:
700 #if 0 /* This should be filled if Wine's DIBSection did understand BI_BITFIELDS */
701             b_info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
702             break;
703 #endif
704
705         case 24:
706             b_info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
707             break;
708
709         default:
710             b_info = (BITMAPINFO *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
711                     sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (2 << desc.ddpfPixelFormat.u.dwRGBBitCount));
712             break;
713         }
714
715         b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
716         b_info->bmiHeader.biWidth = desc.dwWidth;
717         b_info->bmiHeader.biHeight = -desc.dwHeight;
718         b_info->bmiHeader.biPlanes = 1;
719         b_info->bmiHeader.biBitCount = desc.ddpfPixelFormat.u.dwRGBBitCount;
720 #if 0
721         if ((desc.ddpfPixelFormat.u.dwRGBBitCount != 16) &&
722             (desc.ddpfPixelFormat.u.dwRGBBitCount != 32))
723 #endif
724         b_info->bmiHeader.biCompression = BI_RGB;
725 #if 0
726         else
727         b_info->bmiHeader.biCompression = BI_BITFIELDS;
728 #endif
729         b_info->bmiHeader.biSizeImage = (desc.ddpfPixelFormat.u.dwRGBBitCount / 8) * desc.dwWidth * desc.dwHeight;
730         b_info->bmiHeader.biXPelsPerMeter = 0;
731         b_info->bmiHeader.biYPelsPerMeter = 0;
732         b_info->bmiHeader.biClrUsed = 0;
733         b_info->bmiHeader.biClrImportant = 0;
734
735         switch (desc.ddpfPixelFormat.u.dwRGBBitCount) {
736         case 16:
737         case 32:
738 #if 0
739             {
740                 DWORD *masks = (DWORD *) &(b_info->bmiColors);
741
742                 usage = 0;
743                 masks[0] = desc.ddpfPixelFormat.u1.dwRBitMask;
744                 masks[1] = desc.ddpfPixelFormat.u2.dwGBitMask;
745                 masks[2] = desc.ddpfPixelFormat.u3.dwBBitMask;
746             }
747             break;
748 #endif
749         case 24:
750             /* Nothing to do */
751             usage = DIB_RGB_COLORS;
752             break;
753
754         default: {
755                 int i;
756
757                 /* Fill the palette */
758                 usage = DIB_RGB_COLORS;
759
760                 if (This->s.palette == NULL) {
761                     ERR("Bad palette !!!\n");
762                 } else {
763                     RGBQUAD *rgb = (RGBQUAD *) &(b_info->bmiColors);
764                     PALETTEENTRY *pent = (PALETTEENTRY *)&(This->s.palette->palents);
765
766                     for (i=0;i<(1<<desc.ddpfPixelFormat.u.dwRGBBitCount);i++) {
767                         rgb[i].rgbBlue = pent[i].peBlue;
768                         rgb[i].rgbRed = pent[i].peRed;
769                         rgb[i].rgbGreen = pent[i].peGreen; 
770                     }
771                 }
772             }
773             break;
774         }
775         ddc = CreateDCA("DISPLAY",NULL,NULL,NULL);
776         This->s.DIBsection = ddc ? DIB_CreateDIBSection(ddc,
777             b_info,
778             usage,
779             &(This->s.bitmap_data),
780             0,
781             (DWORD)desc.u1.lpSurface,
782             desc.lPitch
783         ) : 0;
784         if (!This->s.DIBsection) {
785                 ERR("CreateDIBSection failed!\n");
786                 if (ddc) DeleteDC(ddc);
787                 HeapFree(GetProcessHeap(), 0, b_info);
788                 return E_FAIL;
789         }
790         TRACE("DIBSection at : %p\n", This->s.bitmap_data);
791
792         /* b_info is not useful anymore */
793         HeapFree(GetProcessHeap(), 0, b_info);
794
795         /* Create the DC */
796         This->s.hdc = CreateCompatibleDC(ddc);
797         This->s.holdbitmap = SelectObject(This->s.hdc, This->s.DIBsection);
798
799         if (ddc) DeleteDC(ddc);
800     }
801
802     if (This->s.bitmap_data != desc.u1.lpSurface) {
803         FIXME("DIBSection not created for frame buffer, reverting to old code\n");
804         /* Copy our surface in the DIB section */
805         if ((GET_BPP(desc) * desc.dwWidth) == desc.lPitch)
806             memcpy(This->s.bitmap_data,desc.u1.lpSurface,desc.lPitch*desc.dwHeight);
807         else
808             /* TODO */
809             FIXME("This case has to be done :/\n");
810     }
811
812     if (lphdc) {
813         TRACE("HDC : %08lx\n", (DWORD) This->s.hdc);
814         *lphdc = This->s.hdc;
815     }
816
817     return DD_OK;
818 }
819
820 HRESULT WINAPI IDirectDrawSurface4Impl_ReleaseDC(LPDIRECTDRAWSURFACE4 iface,HDC hdc) {
821     ICOM_THIS(IDirectDrawSurface4Impl,iface);
822
823     TRACE("(%p)->(0x%08lx)\n",This,(long)hdc);
824
825     if (This->s.bitmap_data != This->s.surface_desc.u1.lpSurface) {
826         TRACE( "Copying DIBSection at : %p\n", This->s.bitmap_data);
827         /* Copy the DIB section to our surface */
828         if ((GET_BPP(This->s.surface_desc) * This->s.surface_desc.dwWidth) == This->s.surface_desc.lPitch) {
829             memcpy(This->s.surface_desc.u1.lpSurface, This->s.bitmap_data, This->s.surface_desc.lPitch * This->s.surface_desc.dwHeight);
830         } else {
831             /* TODO */
832             FIXME("This case has to be done :/\n");
833         }
834     }
835     /* Unlock the surface */
836     IDirectDrawSurface4_Unlock(iface,This->s.surface_desc.u1.lpSurface);
837     return DD_OK;
838 }
839
840 HRESULT WINAPI IDirectDrawSurface4Impl_QueryInterface(
841     LPDIRECTDRAWSURFACE4 iface,REFIID refiid,LPVOID *obj
842 ) {
843     ICOM_THIS(IDirectDrawSurface4Impl,iface);
844
845     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
846     
847     /* All DirectDrawSurface versions (1, 2, 3 and 4) use
848      * the same interface. And IUnknown does that too of course.
849      */
850     if ( IsEqualGUID( &IID_IDirectDrawSurface4, refiid )        ||
851          IsEqualGUID( &IID_IDirectDrawSurface3, refiid )        ||
852          IsEqualGUID( &IID_IDirectDrawSurface2, refiid )        ||
853          IsEqualGUID( &IID_IDirectDrawSurface,  refiid )        ||
854          IsEqualGUID( &IID_IUnknown,            refiid )
855     ) {
856             *obj = This;
857             IDirectDrawSurface4_AddRef(iface);
858
859             TRACE("  Creating IDirectDrawSurface interface (%p)\n", *obj);
860             return S_OK;
861     }
862     FIXME("(%p):interface for IID %s NOT found!\n",This,debugstr_guid(refiid));
863     return OLE_E_ENUM_NOMORE;
864 }
865
866 HRESULT WINAPI IDirectDrawSurface4Impl_IsLost(LPDIRECTDRAWSURFACE4 iface) {
867     ICOM_THIS(IDirectDrawSurface4Impl,iface);
868     TRACE("(%p)->(), stub!\n",This);
869     return DD_OK; /* hmm */
870 }
871
872 HRESULT WINAPI IDirectDrawSurface4Impl_EnumAttachedSurfaces(
873     LPDIRECTDRAWSURFACE4 iface,LPVOID context,LPDDENUMSURFACESCALLBACK esfcb
874 ) {
875     ICOM_THIS(IDirectDrawSurface4Impl,iface);
876     int i;
877     struct _surface_chain *chain = This->s.chain;
878
879     TRACE("(%p)->(%p,%p)\n",This,context,esfcb);
880     if (chain) {
881         for (i=0;i<chain->nrofsurfaces;i++) {
882             TRACE( "Enumerating attached surface (%p)\n", chain->surfaces[i]);
883             if (esfcb((LPDIRECTDRAWSURFACE) chain->surfaces[i], &(chain->surfaces[i]->s.surface_desc), context) == DDENUMRET_CANCEL)
884                 return DD_OK; /* FIXME: return value correct? */
885         }
886     }
887     return DD_OK;
888 }
889
890 HRESULT WINAPI IDirectDrawSurface4Impl_Restore(LPDIRECTDRAWSURFACE4 iface) {
891     ICOM_THIS(IDirectDrawSurface4Impl,iface);
892     FIXME("(%p)->(),stub!\n",This);
893     return DD_OK;
894 }
895
896 HRESULT WINAPI IDirectDrawSurface4Impl_SetColorKey(
897     LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags, LPDDCOLORKEY ckey ) 
898 {
899     ICOM_THIS(IDirectDrawSurface4Impl,iface);
900     TRACE("(%p)->(0x%08lx,%p)\n",This,dwFlags,ckey);
901     if (TRACE_ON(ddraw)) {
902         _dump_colorkeyflag(dwFlags);
903         DPRINTF(" : ");
904         _dump_DDCOLORKEY((void *) ckey);
905         DPRINTF("\n");
906     }
907
908     /* If this surface was loaded as a texture, call also the texture
909      * SetColorKey callback. FIXME: hack approach :(
910      */
911     if (This->s.texture)
912         This->s.SetColorKey_cb(This->s.texture, dwFlags, ckey);
913
914     if( dwFlags & DDCKEY_SRCBLT ) {
915         dwFlags &= ~DDCKEY_SRCBLT;
916         This->s.surface_desc.dwFlags |= DDSD_CKSRCBLT;
917         memcpy( &(This->s.surface_desc.ddckCKSrcBlt), ckey, sizeof( *ckey ) );
918     }
919
920     if( dwFlags & DDCKEY_DESTBLT ) {
921         dwFlags &= ~DDCKEY_DESTBLT;
922         This->s.surface_desc.dwFlags |= DDSD_CKDESTBLT;
923         memcpy( &(This->s.surface_desc.ddckCKDestBlt), ckey, sizeof( *ckey ) );
924     }
925
926     if( dwFlags & DDCKEY_SRCOVERLAY ) {
927         dwFlags &= ~DDCKEY_SRCOVERLAY;
928         This->s.surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
929         memcpy( &(This->s.surface_desc.ddckCKSrcOverlay), ckey, sizeof( *ckey ) );         
930     }
931
932     if( dwFlags & DDCKEY_DESTOVERLAY ) {
933         dwFlags &= ~DDCKEY_DESTOVERLAY;
934         This->s.surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
935         memcpy( &(This->s.surface_desc.ddckCKDestOverlay), ckey, sizeof( *ckey ) );        
936     }
937     if( dwFlags )
938         FIXME("unhandled dwFlags: 0x%08lx\n", dwFlags );
939     return DD_OK;
940 }
941
942 HRESULT WINAPI IDirectDrawSurface4Impl_AddOverlayDirtyRect(
943     LPDIRECTDRAWSURFACE4 iface, LPRECT lpRect
944 ) {
945   ICOM_THIS(IDirectDrawSurface4Impl,iface);
946   FIXME("(%p)->(%p),stub!\n",This,lpRect); 
947
948   return DD_OK;
949 }
950
951 HRESULT WINAPI IDirectDrawSurface4Impl_DeleteAttachedSurface(
952     LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags,
953     LPDIRECTDRAWSURFACE4 lpDDSAttachedSurface
954 ) {
955     ICOM_THIS(IDirectDrawSurface4Impl,iface);
956     int i;
957     struct _surface_chain *chain;
958
959     TRACE("(%p)->(0x%08lx,%p)\n",This,dwFlags,lpDDSAttachedSurface);
960     chain = This->s.chain;
961     for (i=0;i<chain->nrofsurfaces;i++) {
962         if ((IDirectDrawSurface4Impl*)lpDDSAttachedSurface==chain->surfaces[i]){
963             /* There is no AddRef in AddAttachedSurface, so why a release here :-) 
964                IDirectDrawSurface4_Release(lpDDSAttachedSurface); */
965
966             chain->surfaces[i]->s.chain = NULL;
967             memcpy( chain->surfaces+i,
968                     chain->surfaces+(i+1),
969                     (chain->nrofsurfaces-i-1)*sizeof(chain->surfaces[i])
970             );
971             chain->surfaces = HeapReAlloc(
972                 GetProcessHeap(),
973                 0,
974                 chain->surfaces,
975                 sizeof(chain->surfaces[i])*(chain->nrofsurfaces-1)
976             );
977             chain->nrofsurfaces--;
978             return DD_OK;
979         }
980     }
981     return DD_OK;
982 }
983
984 HRESULT WINAPI IDirectDrawSurface4Impl_EnumOverlayZOrders(
985     LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags, LPVOID lpContext,
986     LPDDENUMSURFACESCALLBACK lpfnCallback
987 ) {
988   ICOM_THIS(IDirectDrawSurface4Impl,iface);
989   FIXME("(%p)->(0x%08lx,%p,%p),stub!\n", This,dwFlags,
990           lpContext, lpfnCallback );
991
992   return DD_OK;
993 }
994
995 HRESULT WINAPI IDirectDrawSurface4Impl_GetClipper(
996     LPDIRECTDRAWSURFACE4 iface, LPDIRECTDRAWCLIPPER* lplpDDClipper
997 ) {
998   ICOM_THIS(IDirectDrawSurface4Impl,iface);
999   FIXME("(%p)->(%p),stub!\n", This, lplpDDClipper);
1000
1001   return DD_OK;
1002 }
1003
1004 HRESULT WINAPI IDirectDrawSurface4Impl_GetColorKey(
1005     LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags, LPDDCOLORKEY lpDDColorKey
1006 ) {
1007     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1008     TRACE("(%p)->(0x%08lx,%p)\n", This, dwFlags, lpDDColorKey);
1009
1010     if( dwFlags & DDCKEY_SRCBLT )  {
1011         dwFlags &= ~DDCKEY_SRCBLT;
1012         memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKSrcBlt), sizeof( *lpDDColorKey ) );
1013     }
1014     if( dwFlags & DDCKEY_DESTBLT ) {
1015         dwFlags &= ~DDCKEY_DESTBLT;
1016         memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKDestBlt), sizeof( *lpDDColorKey ) );
1017     }
1018     if( dwFlags & DDCKEY_SRCOVERLAY ) {
1019         dwFlags &= ~DDCKEY_SRCOVERLAY;
1020         memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKSrcOverlay), sizeof( *lpDDColorKey ) );
1021     }
1022     if( dwFlags & DDCKEY_DESTOVERLAY ) {
1023         dwFlags &= ~DDCKEY_DESTOVERLAY;
1024         memcpy( lpDDColorKey, &(This->s.surface_desc.ddckCKDestOverlay), sizeof( *lpDDColorKey ) );
1025     }
1026     if( dwFlags )
1027         FIXME("unhandled dwFlags: 0x%08lx\n", dwFlags );
1028     return DD_OK;
1029 }
1030
1031 HRESULT WINAPI IDirectDrawSurface4Impl_GetFlipStatus(
1032     LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags
1033 ) {
1034     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1035     FIXME("(%p)->(0x%08lx),stub!\n", This, dwFlags);
1036
1037     return DD_OK;
1038 }
1039
1040 HRESULT WINAPI IDirectDrawSurface4Impl_GetPalette(
1041     LPDIRECTDRAWSURFACE4 iface, LPDIRECTDRAWPALETTE* lplpDDPalette
1042 ) {
1043     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1044     TRACE("(%p)->(%p),stub!\n", This, lplpDDPalette);
1045
1046     if (!This->s.palette)
1047         return DDERR_NOPALETTEATTACHED;
1048
1049     IDirectDrawPalette_AddRef( (IDirectDrawPalette*) This->s.palette );
1050     *lplpDDPalette = (IDirectDrawPalette*) This->s.palette;
1051     return DD_OK;
1052 }
1053
1054 HRESULT WINAPI IDirectDrawSurface4Impl_SetOverlayPosition(
1055     LPDIRECTDRAWSURFACE4 iface, LONG lX, LONG lY
1056 ) {
1057     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1058     FIXME("(%p)->(%ld,%ld),stub!\n", This, lX, lY);
1059
1060     return DD_OK;
1061 }
1062
1063 HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlay(
1064     LPDIRECTDRAWSURFACE4 iface, LPRECT lpSrcRect,
1065     LPDIRECTDRAWSURFACE4 lpDDDestSurface, LPRECT lpDestRect, DWORD dwFlags,
1066     LPDDOVERLAYFX lpDDOverlayFx
1067 ) {
1068     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1069     FIXME("(%p)->(%p,%p,%p,0x%08lx,%p),stub!\n", This,
1070          lpSrcRect, lpDDDestSurface, lpDestRect, dwFlags, lpDDOverlayFx );  
1071
1072     return DD_OK;
1073 }
1074  
1075 HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlayDisplay(
1076     LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags
1077 ) {
1078     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1079     FIXME("(%p)->(0x%08lx),stub!\n", This, dwFlags); 
1080
1081     return DD_OK;
1082 }
1083
1084 HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlayZOrder(
1085     LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags,LPDIRECTDRAWSURFACE4 lpDDSReference
1086 ) {
1087     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1088     FIXME("(%p)->(0x%08lx,%p),stub!\n", This, dwFlags, lpDDSReference);
1089
1090     return DD_OK;
1091 }
1092
1093 HRESULT WINAPI IDirectDrawSurface4Impl_GetDDInterface(
1094     LPDIRECTDRAWSURFACE4 iface, LPVOID* lplpDD
1095 ) {
1096     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1097     FIXME("(%p)->(%p),stub!\n", This, lplpDD);
1098
1099     /* Not sure about that... */
1100
1101     IDirectDraw_AddRef((LPDIRECTDRAW)This->s.ddraw),
1102     *lplpDD = (void *) This->s.ddraw;
1103
1104     return DD_OK;
1105 }
1106
1107 HRESULT WINAPI IDirectDrawSurface4Impl_PageLock(
1108     LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags
1109 ) {
1110     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1111     FIXME("(%p)->(0x%08lx),stub!\n", This, dwFlags);
1112
1113     return DD_OK;
1114 }
1115
1116 HRESULT WINAPI IDirectDrawSurface4Impl_PageUnlock(
1117     LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags
1118 ) {
1119     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1120     FIXME("(%p)->(0x%08lx),stub!\n", This, dwFlags);
1121
1122     return DD_OK;
1123 }
1124
1125 HRESULT WINAPI IDirectDrawSurface4Impl_SetSurfaceDesc(
1126     LPDIRECTDRAWSURFACE4 iface, LPDDSURFACEDESC lpDDSD, DWORD dwFlags
1127 ) {
1128     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1129     FIXME("(%p)->(%p,0x%08lx),stub!\n", This, lpDDSD, dwFlags);
1130
1131     return DD_OK;
1132 }
1133
1134 HRESULT WINAPI IDirectDrawSurface4Impl_SetPrivateData(
1135     LPDIRECTDRAWSURFACE4 iface, REFGUID guidTag, LPVOID lpData, DWORD cbSize,
1136     DWORD dwFlags
1137 ) {
1138     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1139     FIXME("(%p)->(%p,%p,%ld,%08lx\n", This, guidTag, lpData, cbSize, dwFlags);
1140
1141     return DD_OK;
1142 }
1143
1144 HRESULT WINAPI IDirectDrawSurface4Impl_GetPrivateData(
1145     LPDIRECTDRAWSURFACE4 iface, REFGUID guidTag, LPVOID lpBuffer,
1146     LPDWORD lpcbBufferSize
1147 ) {
1148     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1149     FIXME("(%p)->(%p,%p,%p)\n", This, guidTag, lpBuffer, lpcbBufferSize);
1150
1151     return DD_OK;
1152 }
1153
1154 HRESULT WINAPI IDirectDrawSurface4Impl_FreePrivateData(
1155     LPDIRECTDRAWSURFACE4 iface, REFGUID guidTag
1156 ) {
1157     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1158     FIXME("(%p)->(%p)\n", This, guidTag);
1159
1160     return DD_OK;
1161 }
1162
1163 HRESULT WINAPI IDirectDrawSurface4Impl_GetUniquenessValue(
1164     LPDIRECTDRAWSURFACE4 iface, LPDWORD lpValue
1165 )  {
1166     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1167     FIXME("(%p)->(%p)\n", This, lpValue);
1168
1169     return DD_OK;
1170 }
1171
1172 HRESULT WINAPI IDirectDrawSurface4Impl_ChangeUniquenessValue(
1173     LPDIRECTDRAWSURFACE4 iface
1174 ) {
1175     ICOM_THIS(IDirectDrawSurface4Impl,iface);
1176     FIXME("(%p)\n", This);
1177
1178     return DD_OK;
1179 }