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