ddraw, wined3d: Color keying tests and fixes.
[wine] / dlls / wined3d / surface.c
1 /*
2  * IWineD3DSurface Implementation
3  *
4  * Copyright 1998 Lionel Ulmer
5  * Copyright 2000-2001 TransGaming Technologies Inc.
6  * Copyright 2002-2005 Jason Edmeades
7  * Copyright 2002-2003 Raphael Junqueira
8  * Copyright 2004 Christian Costa
9  * Copyright 2005 Oliver Stieber
10  * Copyright 2006 Stefan Dösinger for CodeWeavers
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26
27 #include "config.h"
28 #include "wine/port.h"
29 #include "wined3d_private.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
32 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info
33
34 typedef enum {
35     NO_CONVERSION,
36     CONVERT_PALETTED,
37     CONVERT_PALETTED_CK,
38     CONVERT_CK_565,
39     CONVERT_CK_5551,
40     CONVERT_CK_4444,
41     CONVERT_CK_4444_ARGB,
42     CONVERT_CK_1555,
43     CONVERT_555,
44     CONVERT_CK_RGB24,
45     CONVERT_CK_8888,
46     CONVERT_CK_8888_ARGB,
47     CONVERT_RGB32_888,
48     CONVERT_V8U8
49 } CONVERT_TYPES;
50
51 HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *surf);
52
53 static void surface_download_data(IWineD3DSurfaceImpl *This) {
54     if (This->resource.format == WINED3DFMT_DXT1 ||
55             This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
56             This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) {
57         if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { /* We can assume this as the texture would not have been created otherwise */
58             FIXME("(%p) : Attempting to lock a compressed texture when texture compression isn't supported by opengl\n", This);
59         } else {
60             TRACE("(%p) : Calling glGetCompressedTexImageARB level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level,
61                 This->glDescription.glFormat, This->glDescription.glType, This->resource.allocatedMemory);
62
63             ENTER_GL();
64
65             GL_EXTCALL(glGetCompressedTexImageARB(This->glDescription.target, This->glDescription.level, This->resource.allocatedMemory));
66             checkGLcall("glGetCompressedTexImageARB()");
67
68             LEAVE_GL();
69         }
70     } else {
71         void *mem;
72         int src_pitch = 0;
73         int dst_pitch = 0;
74
75          if(This->Flags & SFLAG_CONVERTED) {
76              FIXME("Read back converted textures unsupported\n");
77              return;
78          }
79
80         if (This->Flags & SFLAG_NONPOW2) {
81             src_pitch = This->bytesPerPixel * This->pow2Width;
82             dst_pitch = IWineD3DSurface_GetPitch((IWineD3DSurface *) This);
83             src_pitch = (src_pitch + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
84             mem = HeapAlloc(GetProcessHeap(), 0, src_pitch * This->pow2Height);
85         } else {
86             mem = This->resource.allocatedMemory;
87         }
88
89         TRACE("(%p) : Calling glGetTexImage level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level,
90                 This->glDescription.glFormat, This->glDescription.glType, mem);
91
92         ENTER_GL();
93
94         glGetTexImage(This->glDescription.target, This->glDescription.level, This->glDescription.glFormat,
95                 This->glDescription.glType, mem);
96         checkGLcall("glGetTexImage()");
97
98         LEAVE_GL();
99
100         if (This->Flags & SFLAG_NONPOW2) {
101             LPBYTE src_data, dst_data;
102             int y;
103             /*
104              * Some games (e.g. warhammer 40k) don't work properly with the odd pitches, preventing
105              * the surface pitch from being used to box non-power2 textures. Instead we have to use a hack to
106              * repack the texture so that the bpp * width pitch can be used instead of bpp * pow2width.
107              *
108              * We're doing this...
109              *
110              * instead of boxing the texture :
111              * |<-texture width ->|  -->pow2width|   /\
112              * |111111111111111111|              |   |
113              * |222 Texture 222222| boxed empty  | texture height
114              * |3333 Data 33333333|              |   |
115              * |444444444444444444|              |   \/
116              * -----------------------------------   |
117              * |     boxed  empty | boxed empty  | pow2height
118              * |                  |              |   \/
119              * -----------------------------------
120              *
121              *
122              * we're repacking the data to the expected texture width
123              *
124              * |<-texture width ->|  -->pow2width|   /\
125              * |111111111111111111222222222222222|   |
126              * |222333333333333333333444444444444| texture height
127              * |444444                           |   |
128              * |                                 |   \/
129              * |                                 |   |
130              * |            empty                | pow2height
131              * |                                 |   \/
132              * -----------------------------------
133              *
134              * == is the same as
135              *
136              * |<-texture width ->|    /\
137              * |111111111111111111|
138              * |222222222222222222|texture height
139              * |333333333333333333|
140              * |444444444444444444|    \/
141              * --------------------
142              *
143              * this also means that any references to allocatedMemory should work with the data as if were a
144              * standard texture with a non-power2 width instead of texture boxed up to be a power2 texture.
145              *
146              * internally the texture is still stored in a boxed format so any references to textureName will
147              * get a boxed texture with width pow2width and not a texture of width currentDesc.Width.
148              *
149              * Performance should not be an issue, because applications normally do not lock the surfaces when
150              * rendering. If an app does, the SFLAG_DYNLOCK flag will kick in and the memory copy won't be released,
151              * and doesn't have to be re-read.
152              */
153             src_data = mem;
154             dst_data = This->resource.allocatedMemory;
155             TRACE("(%p) : Repacking the surface data from pitch %d to pitch %d\n", This, src_pitch, dst_pitch);
156             for (y = 1 ; y < This->currentDesc.Height; y++) {
157                 /* skip the first row */
158                 src_data += src_pitch;
159                 dst_data += dst_pitch;
160                 memcpy(dst_data, src_data, dst_pitch);
161             }
162
163             HeapFree(GetProcessHeap(), 0, mem);
164         }
165     }
166 }
167
168 static void surface_upload_data(IWineD3DSurfaceImpl *This, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *data) {
169     if (This->resource.format == WINED3DFMT_DXT1 ||
170             This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
171             This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) {
172         if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
173             FIXME("Using DXT1/3/5 without advertized support\n");
174         } else {
175             TRACE("(%p) : Calling glCompressedTexSubImage2D w %d, h %d, data %p\n", This, width, height, data);
176             ENTER_GL();
177             /* glCompressedTexSubImage2D for uploading and glTexImage2D for allocating does not work well on some drivers(r200 dri, MacOS ATI driver)
178              * glCompressedTexImage2D does not accept NULL pointers. So for compressed textures surface_allocate_surface does nothing, and this
179              * function uses glCompressedTexImage2D instead of the SubImage call
180              */
181             GL_EXTCALL(glCompressedTexImage2DARB(This->glDescription.target, This->glDescription.level, This->glDescription.glFormatInternal,
182                        width, height, 0 /* border */, This->resource.size, data));
183             checkGLcall("glCompressedTexSubImage2D");
184             LEAVE_GL();
185         }
186     } else {
187         TRACE("(%p) : Calling glTexSubImage2D w %d,  h %d, data, %p\n", This, width, height, data);
188         ENTER_GL();
189         glTexSubImage2D(This->glDescription.target, This->glDescription.level, 0, 0, width, height, format, type, data);
190         checkGLcall("glTexSubImage2D");
191         LEAVE_GL();
192     }
193 }
194
195 static void surface_allocate_surface(IWineD3DSurfaceImpl *This, GLenum internal, GLsizei width, GLsizei height, GLenum format, GLenum type) {
196     TRACE("(%p) : Creating surface (target %#x)  level %d, d3d format %s, internal format %#x, width %d, height %d, gl format %#x, gl type=%#x\n", This,
197             This->glDescription.target, This->glDescription.level, debug_d3dformat(This->resource.format), internal, width, height, format, type);
198
199     if (This->resource.format == WINED3DFMT_DXT1 ||
200             This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
201             This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) {
202         /* glCompressedTexImage2D does not accept NULL pointers, so we cannot allocate a compressed texture without uploading data */
203         TRACE("Not allocating compressed surfaces, surface_upload_data will specify them\n");
204         return;
205     }
206
207     ENTER_GL();
208
209     glTexImage2D(This->glDescription.target, This->glDescription.level, internal, width, height, 0, format, type, NULL);
210     checkGLcall("glTexImage2D");
211
212     LEAVE_GL();
213 }
214
215 /* *******************************************
216    IWineD3DSurface IUnknown parts follow
217    ******************************************* */
218 HRESULT WINAPI IWineD3DSurfaceImpl_QueryInterface(IWineD3DSurface *iface, REFIID riid, LPVOID *ppobj)
219 {
220     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
221     /* Warn ,but be nice about things */
222     TRACE("(%p)->(%s,%p)\n", This,debugstr_guid(riid),ppobj);
223
224     if (IsEqualGUID(riid, &IID_IUnknown)
225         || IsEqualGUID(riid, &IID_IWineD3DBase)
226         || IsEqualGUID(riid, &IID_IWineD3DResource)
227         || IsEqualGUID(riid, &IID_IWineD3DSurface)) {
228         IUnknown_AddRef((IUnknown*)iface);
229         *ppobj = This;
230         return S_OK;
231     }
232     *ppobj = NULL;
233     return E_NOINTERFACE;
234 }
235
236 ULONG WINAPI IWineD3DSurfaceImpl_AddRef(IWineD3DSurface *iface) {
237     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
238     ULONG ref = InterlockedIncrement(&This->resource.ref);
239     TRACE("(%p) : AddRef increasing from %d\n", This,ref - 1);
240     return ref;
241 }
242
243 ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
244     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
245     ULONG ref = InterlockedDecrement(&This->resource.ref);
246     TRACE("(%p) : Releasing from %d\n", This, ref + 1);
247     if (ref == 0) {
248         IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->resource.wineD3DDevice;
249         TRACE("(%p) : cleaning up\n", This);
250         if (This->glDescription.textureName != 0) { /* release the openGL texture.. */
251             ENTER_GL();
252             TRACE("Deleting texture %d\n", This->glDescription.textureName);
253             glDeleteTextures(1, &This->glDescription.textureName);
254             LEAVE_GL();
255         }
256
257         if(This->Flags & SFLAG_DIBSECTION) {
258             /* Release the DC */
259             SelectObject(This->hDC, This->dib.holdbitmap);
260             DeleteDC(This->hDC);
261             /* Release the DIB section */
262             DeleteObject(This->dib.DIBsection);
263             This->dib.bitmap_data = NULL;
264             This->resource.allocatedMemory = NULL;
265         }
266         if(This->Flags & SFLAG_USERPTR) IWineD3DSurface_SetMem(iface, NULL);
267
268         IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
269         if(iface == device->ddraw_primary)
270             device->ddraw_primary = NULL;
271
272         if(iface == device->lastActiveRenderTarget) {
273             device->lastActiveRenderTarget = NULL;
274         }
275
276         TRACE("(%p) Released\n", This);
277         HeapFree(GetProcessHeap(), 0, This);
278
279     }
280     return ref;
281 }
282
283 /* ****************************************************
284    IWineD3DSurface IWineD3DResource parts follow
285    **************************************************** */
286 HRESULT WINAPI IWineD3DSurfaceImpl_GetDevice(IWineD3DSurface *iface, IWineD3DDevice** ppDevice) {
287     return IWineD3DResourceImpl_GetDevice((IWineD3DResource *)iface, ppDevice);
288 }
289
290 HRESULT WINAPI IWineD3DSurfaceImpl_SetPrivateData(IWineD3DSurface *iface, REFGUID refguid, CONST void* pData, DWORD SizeOfData, DWORD Flags) {
291     return IWineD3DResourceImpl_SetPrivateData((IWineD3DResource *)iface, refguid, pData, SizeOfData, Flags);
292 }
293
294 HRESULT WINAPI IWineD3DSurfaceImpl_GetPrivateData(IWineD3DSurface *iface, REFGUID refguid, void* pData, DWORD* pSizeOfData) {
295     return IWineD3DResourceImpl_GetPrivateData((IWineD3DResource *)iface, refguid, pData, pSizeOfData);
296 }
297
298 HRESULT WINAPI IWineD3DSurfaceImpl_FreePrivateData(IWineD3DSurface *iface, REFGUID refguid) {
299     return IWineD3DResourceImpl_FreePrivateData((IWineD3DResource *)iface, refguid);
300 }
301
302 DWORD   WINAPI IWineD3DSurfaceImpl_SetPriority(IWineD3DSurface *iface, DWORD PriorityNew) {
303     return IWineD3DResourceImpl_SetPriority((IWineD3DResource *)iface, PriorityNew);
304 }
305
306 DWORD   WINAPI IWineD3DSurfaceImpl_GetPriority(IWineD3DSurface *iface) {
307     return IWineD3DResourceImpl_GetPriority((IWineD3DResource *)iface);
308 }
309
310 void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) {
311     /* TODO: re-write the way textures and managed,
312     *  use a 'opengl context manager' to manage RenderTarget surfaces
313     ** *********************************************************/
314
315     /* TODO: check for locks */
316     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
317     IWineD3DBaseTexture *baseTexture = NULL;
318     TRACE("(%p)Checking to see if the container is a base texture\n", This);
319     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
320         TRACE("Passing to conatiner\n");
321         IWineD3DBaseTexture_PreLoad(baseTexture);
322         IWineD3DBaseTexture_Release(baseTexture);
323     } else {
324     TRACE("(%p) : About to load surface\n", This);
325     ENTER_GL();
326 #if 0 /* TODO: context manager support */
327      IWineD3DContextManager_PushState(This->contextManager, GL_TEXTURE_2D, ENABLED, NOW /* make sure the state is applied now */);
328 #endif
329     glEnable(This->glDescription.target);/* make sure texture support is enabled in this context */
330     if (!This->glDescription.level) {
331         if (!This->glDescription.textureName) {
332             glGenTextures(1, &This->glDescription.textureName);
333             checkGLcall("glGenTextures");
334             TRACE("Surface %p given name %d\n", This, This->glDescription.textureName);
335         }
336         glBindTexture(This->glDescription.target, This->glDescription.textureName);
337         checkGLcall("glBindTexture");
338         IWineD3DSurface_LoadTexture(iface);
339         /* This is where we should be reducing the amount of GLMemoryUsed */
340     } else if (This->glDescription.textureName) { /* NOTE: the level 0 surface of a mpmapped texture must be loaded first! */
341         /* assume this is a coding error not a real error for now */
342         FIXME("Mipmap surface has a glTexture bound to it!\n");
343     }
344     if (This->resource.pool == WINED3DPOOL_DEFAULT) {
345        /* Tell opengl to try and keep this texture in video ram (well mostly) */
346        GLclampf tmp;
347        tmp = 0.9f;
348         glPrioritizeTextures(1, &This->glDescription.textureName, &tmp);
349     }
350     /* TODO: disable texture support, if it wastn't enabled when we entered. */
351 #if 0 /* TODO: context manager support */
352      IWineD3DContextManager_PopState(This->contextManager, GL_TEXTURE_2D, DISABLED,DELAYED
353               /* we don't care when the state is disabled(if atall) */);
354 #endif
355     LEAVE_GL();
356     }
357     return;
358 }
359
360 WINED3DRESOURCETYPE WINAPI IWineD3DSurfaceImpl_GetType(IWineD3DSurface *iface) {
361     TRACE("(%p) : calling resourceimpl_GetType\n", iface);
362     return IWineD3DResourceImpl_GetType((IWineD3DResource *)iface);
363 }
364
365 HRESULT WINAPI IWineD3DSurfaceImpl_GetParent(IWineD3DSurface *iface, IUnknown **pParent) {
366     TRACE("(%p) : calling resourceimpl_GetParent\n", iface);
367     return IWineD3DResourceImpl_GetParent((IWineD3DResource *)iface, pParent);
368 }
369
370 /* ******************************************************
371    IWineD3DSurface IWineD3DSurface parts follow
372    ****************************************************** */
373
374 HRESULT WINAPI IWineD3DSurfaceImpl_GetContainer(IWineD3DSurface* iface, REFIID riid, void** ppContainer) {
375     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
376     IWineD3DBase *container = 0;
377
378     TRACE("(This %p, riid %s, ppContainer %p)\n", This, debugstr_guid(riid), ppContainer);
379
380     if (!ppContainer) {
381         ERR("Called without a valid ppContainer.\n");
382     }
383
384     /** From MSDN:
385      * If the surface is created using CreateImageSurface/CreateOffscreenPlainSurface, CreateRenderTarget,
386      * or CreateDepthStencilSurface, the surface is considered stand alone. In this case,
387      * GetContainer will return the Direct3D device used to create the surface.
388      */
389     if (This->container) {
390         container = This->container;
391     } else {
392         container = (IWineD3DBase *)This->resource.wineD3DDevice;
393     }
394
395     TRACE("Relaying to QueryInterface\n");
396     return IUnknown_QueryInterface(container, riid, ppContainer);
397 }
398
399 HRESULT WINAPI IWineD3DSurfaceImpl_GetDesc(IWineD3DSurface *iface, WINED3DSURFACE_DESC *pDesc) {
400     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
401
402     TRACE("(%p) : copying into %p\n", This, pDesc);
403     if(pDesc->Format != NULL)             *(pDesc->Format) = This->resource.format;
404     if(pDesc->Type != NULL)               *(pDesc->Type)   = This->resource.resourceType;
405     if(pDesc->Usage != NULL)              *(pDesc->Usage)              = This->resource.usage;
406     if(pDesc->Pool != NULL)               *(pDesc->Pool)               = This->resource.pool;
407     if(pDesc->Size != NULL)               *(pDesc->Size)               = This->resource.size;   /* dx8 only */
408     if(pDesc->MultiSampleType != NULL)    *(pDesc->MultiSampleType)    = This->currentDesc.MultiSampleType;
409     if(pDesc->MultiSampleQuality != NULL) *(pDesc->MultiSampleQuality) = This->currentDesc.MultiSampleQuality;
410     if(pDesc->Width != NULL)              *(pDesc->Width)              = This->currentDesc.Width;
411     if(pDesc->Height != NULL)             *(pDesc->Height)             = This->currentDesc.Height;
412     return WINED3D_OK;
413 }
414
415 void WINAPI IWineD3DSurfaceImpl_SetGlTextureDesc(IWineD3DSurface *iface, UINT textureName, int target) {
416     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
417     TRACE("(%p) : setting textureName %u, target %i\n", This, textureName, target);
418     if (This->glDescription.textureName == 0 && textureName != 0) {
419         This->Flags |= SFLAG_DIRTY;
420         IWineD3DSurface_AddDirtyRect(iface, NULL);
421     }
422     This->glDescription.textureName = textureName;
423     This->glDescription.target      = target;
424 }
425
426 void WINAPI IWineD3DSurfaceImpl_GetGlDesc(IWineD3DSurface *iface, glDescriptor **glDescription) {
427     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
428     TRACE("(%p) : returning %p\n", This, &This->glDescription);
429     *glDescription = &This->glDescription;
430 }
431
432 /* TODO: think about moving this down to resource? */
433 const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface) {
434     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
435     /* This should only be called for sysmem textures, it may be a good idea to extend this to all pools at some point in the futture  */
436     if (This->resource.pool != WINED3DPOOL_SYSTEMMEM) {
437         FIXME(" (%p)Attempting to get system memory for a non-system memory texture\n", iface);
438     }
439     return (CONST void*)(This->resource.allocatedMemory);
440 }
441
442 static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, void *dest, UINT pitch, BOOL srcUpsideDown) {
443     BYTE *mem;
444     GLint fmt;
445     GLint type;
446     BYTE *row, *top, *bottom;
447     int i;
448     BOOL bpp;
449
450     switch(This->resource.format)
451     {
452         case WINED3DFMT_P8:
453         {
454             /* GL can't return palettized data, so read ARGB pixels into a
455              * separate block of memory and convert them into palettized format
456              * in software. Slow, but if the app means to use palettized render
457              * targets and locks it...
458              *
459              * Use GL_RGB, GL_UNSIGNED_BYTE to read the surface for performance reasons
460              * Don't use GL_BGR as in the WINED3DFMT_R8G8B8 case, instead watch out
461              * for the color channels when palettizing the colors.
462              */
463             fmt = GL_RGB;
464             type = GL_UNSIGNED_BYTE;
465             pitch *= 3;
466             mem = HeapAlloc(GetProcessHeap(), 0, This->resource.size * 3);
467             if(!mem) {
468                 ERR("Out of memory\n");
469                 return;
470             }
471             bpp = This->bytesPerPixel * 3;
472         }
473         break;
474
475         default:
476             mem = dest;
477             fmt = This->glDescription.glFormat;
478             type = This->glDescription.glType;
479             bpp = This->bytesPerPixel;
480     }
481
482     glReadPixels(rect->left, rect->top,
483                  rect->right - rect->left,
484                  rect->bottom - rect->top,
485                  fmt, type, mem);
486     vcheckGLcall("glReadPixels");
487
488     /* TODO: Merge this with the palettization loop below for P8 targets */
489
490     if(!srcUpsideDown) {
491         UINT len, off;
492         /* glReadPixels returns the image upside down, and there is no way to prevent this.
493             Flip the lines in software */
494         len = (rect->right - rect->left) * bpp;
495         off = rect->left * bpp;
496
497         row = HeapAlloc(GetProcessHeap(), 0, len);
498         if(!row) {
499             ERR("Out of memory\n");
500             if(This->resource.format == WINED3DFMT_P8) HeapFree(GetProcessHeap(), 0, mem);
501             return;
502         }
503
504         top = mem + pitch * rect->top;
505         bottom = ((BYTE *) mem) + pitch * ( rect->bottom - rect->top - 1);
506         for(i = 0; i < (rect->bottom - rect->top) / 2; i++) {
507             memcpy(row, top + off, len);
508             memcpy(top + off, bottom + off, len);
509             memcpy(bottom + off, row, len);
510             top += pitch;
511             bottom -= pitch;
512         }
513         HeapFree(GetProcessHeap(), 0, row);
514     }
515
516     if(This->resource.format == WINED3DFMT_P8) {
517         PALETTEENTRY *pal;
518         DWORD width = pitch / 3;
519         int x, y, c;
520         if(This->palette) {
521             pal = This->palette->palents;
522         } else {
523             pal = This->resource.wineD3DDevice->palettes[This->resource.wineD3DDevice->currentPalette];
524         }
525
526         for(y = rect->top; y < rect->bottom; y++) {
527             for(x = rect->left; x < rect->right; x++) {
528                 /*                      start              lines            pixels      */
529                 BYTE *blue =  (BYTE *) ((BYTE *) mem) + y * pitch + x * (sizeof(BYTE) * 3);
530                 BYTE *green = blue  + 1;
531                 BYTE *red =   green + 1;
532
533                 for(c = 0; c < 256; c++) {
534                     if(*red   == pal[c].peRed   &&
535                        *green == pal[c].peGreen &&
536                        *blue  == pal[c].peBlue)
537                     {
538                         *((BYTE *) dest + y * width + x) = c;
539                         break;
540                     }
541                 }
542             }
543         }
544         HeapFree(GetProcessHeap(), 0, mem);
545     }
546 }
547
548 static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
549     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
550     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
551     IWineD3DSwapChainImpl *swapchain = NULL;
552
553     TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
554
555     if (!(This->Flags & SFLAG_LOCKABLE)) {
556         /* Note: UpdateTextures calls CopyRects which calls this routine to populate the
557               texture regions, and since the destination is an unlockable region we need
558               to tolerate this                                                           */
559         TRACE("Warning: trying to lock unlockable surf@%p\n", This);
560         /*return WINED3DERR_INVALIDCALL; */
561     }
562
563     pLockedRect->Pitch = IWineD3DSurface_GetPitch(iface);
564
565     /* Mark the surface locked */
566     This->Flags |= SFLAG_LOCKED;
567
568     /* Whatever surface we have, make sure that there is memory allocated for the downloaded copy */
569     if(!This->resource.allocatedMemory) {
570         This->resource.allocatedMemory = HeapAlloc(GetProcessHeap() ,0 , This->resource.size + 4);
571         This->Flags |= SFLAG_GLDIRTY; /* This is the marker that surface data has to be downloaded */
572     }
573
574     /* Calculate the correct start address to report */
575     if (NULL == pRect) {
576         pLockedRect->pBits = This->resource.allocatedMemory;
577         This->lockedRect.left   = 0;
578         This->lockedRect.top    = 0;
579         This->lockedRect.right  = This->currentDesc.Width;
580         This->lockedRect.bottom = This->currentDesc.Height;
581         TRACE("Locked Rect (%p) = l %d, t %d, r %d, b %d\n", &This->lockedRect, This->lockedRect.left, This->lockedRect.top, This->lockedRect.right, This->lockedRect.bottom);
582     } else {
583         TRACE("Lock Rect (%p) = l %d, t %d, r %d, b %d\n", pRect, pRect->left, pRect->top, pRect->right, pRect->bottom);
584
585         if ((pRect->top < 0) ||
586              (pRect->left < 0) ||
587              (pRect->left >= pRect->right) ||
588              (pRect->top >= pRect->bottom) ||
589              (pRect->right > This->currentDesc.Width) ||
590              (pRect->bottom > This->currentDesc.Height))
591         {
592             WARN(" Invalid values in pRect !!!\n");
593             return D3DERR_INVALIDCALL;
594         }
595
596         if (This->resource.format == WINED3DFMT_DXT1) { /* DXT1 is half byte per pixel */
597             pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + ((pRect->left * This->bytesPerPixel / 2));
598         } else {
599             pLockedRect->pBits = This->resource.allocatedMemory + (pLockedRect->Pitch * pRect->top) + (pRect->left * This->bytesPerPixel);
600         }
601         This->lockedRect.left   = pRect->left;
602         This->lockedRect.top    = pRect->top;
603         This->lockedRect.right  = pRect->right;
604         This->lockedRect.bottom = pRect->bottom;
605     }
606
607     if (This->Flags & SFLAG_NONPOW2) {
608         TRACE("Locking non-power 2 texture\n");
609     }
610
611     /* Performance optimization: Count how often a surface is locked, if it is locked regularly do not throw away the system memory copy.
612      * This avoids the need to download the surface from opengl all the time. The surface is still downloaded if the opengl texture is
613      * changed
614      */
615     if(!(This->Flags & SFLAG_DYNLOCK)) {
616         This->lockCount++;
617         /* MAXLOCKCOUNT is defined in wined3d_private.h */
618         if(This->lockCount > MAXLOCKCOUNT) {
619             TRACE("Surface is locked regularily, not freeing the system memory copy any more\n");
620             This->Flags |= SFLAG_DYNLOCK;
621         }
622     }
623
624     if((Flags & WINED3DLOCK_DISCARD) || !(This->Flags & SFLAG_GLDIRTY) ) {
625         TRACE("WINED3DLOCK_DISCARD flag passed, or local copy is up to date, not downloading data\n");
626         goto lock_end;
627     }
628
629     /* Now download the surface content from opengl
630      * Use the render target readback if the surface is on a swapchain(=onscreen render target) or the current primary target
631      * Offscreen targets which are not active at the moment or are higher targets(fbos) can be locked with the texture path
632      */
633     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
634     if(swapchain || iface == myDevice->render_targets[0]) {
635         BOOL srcIsUpsideDown;
636
637         if(wined3d_settings.rendertargetlock_mode == RTL_DISABLE) {
638             static BOOL warned = FALSE;
639             if(!warned) {
640                 ERR("The application tries to lock the render target, but render target locking is disabled\n");
641                 warned = TRUE;
642             }
643             if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
644             return WINED3D_OK;
645         }
646
647         /* Activate the surface. Set it up for blitting now, although not necessarily needed for LockRect.
648          * Certain graphics drivers seem to dislike some enabled states when reading from opengl, the blitting usage
649          * should help here. Furthermore unlockrect will need the context set up for blitting. The context manager will find
650          * context->last_was_blit set on the unlock.
651          */
652         ENTER_GL();
653         ActivateContext(myDevice, iface, CTXUSAGE_BLIT);
654
655         /* Select the correct read buffer, and give some debug output.
656          * There is no need to keep track of the current read buffer or reset it, every part of the code
657          * that reads sets the read buffer as desired.
658          */
659         if(!swapchain) {
660             /* Locking the primary render target which is not on a swapchain(=offscreen render target).
661              * Read from the back buffer
662              */
663             TRACE("Locking offscreen render target\n");
664             glReadBuffer(GL_BACK);
665             srcIsUpsideDown = TRUE;
666         } else {
667             if(iface == swapchain->frontBuffer) {
668                 TRACE("Locking the front buffer\n");
669                 glReadBuffer(GL_FRONT);
670             } else if(swapchain->backBuffer && iface == swapchain->backBuffer[0]) {
671                 TRACE("Locking the back buffer\n");
672                 glReadBuffer(GL_BACK);
673             } else {
674                 /* Ok, there is an issue: OpenGL does not guarant any back buffer number, so all we can do is to read GL_BACK
675                  * and hope it gives what the app wants
676                  */
677                 FIXME("Application is locking a 2nd or higher back buffer\n");
678                 glReadBuffer(GL_BACK);
679             }
680             IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
681             srcIsUpsideDown = FALSE;
682         }
683
684         switch(wined3d_settings.rendertargetlock_mode) {
685             case RTL_AUTO:
686             case RTL_READDRAW:
687             case RTL_READTEX:
688                 read_from_framebuffer(This, &This->lockedRect, This->resource.allocatedMemory, pLockedRect->Pitch, srcIsUpsideDown);
689                 break;
690
691             case RTL_TEXDRAW:
692             case RTL_TEXTEX:
693                 read_from_framebuffer(This, &This->lockedRect, This->resource.allocatedMemory, pLockedRect->Pitch, srcIsUpsideDown);
694                 FIXME("Reading from render target with a texture isn't implemented yet, falling back to framebuffer reading\n");
695                 break;
696         }
697         LEAVE_GL();
698
699         /* Mark the local copy up to date if a full download was done */
700         if(This->lockedRect.left == 0 &&
701            This->lockedRect.top == 0 &&
702            This->lockedRect.right == This->currentDesc.Width &&
703            This->lockedRect.bottom == This->currentDesc.Height) {
704             This->Flags &= ~SFLAG_GLDIRTY;
705         }
706     } else if(iface == myDevice->stencilBufferTarget) {
707         /** the depth stencil in openGL has a format of GL_FLOAT
708          * which should be good for WINED3DFMT_D16_LOCKABLE
709          * and WINED3DFMT_D16
710          * it is unclear what format the stencil buffer is in except.
711          * 'Each index is converted to fixed point...
712          * If GL_MAP_STENCIL is GL_TRUE, indices are replaced by their
713          * mappings in the table GL_PIXEL_MAP_S_TO_S.
714          * glReadPixels(This->lockedRect.left,
715          *             This->lockedRect.bottom - j - 1,
716          *             This->lockedRect.right - This->lockedRect.left,
717          *             1,
718          *             GL_DEPTH_COMPONENT,
719          *             type,
720          *             (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
721          *
722          * Depth Stencil surfaces which are not the current depth stencil target should have their data in a
723          * gl texture(next path), or in local memory(early return because of missing SFLAG_GLDIRTY above). If
724          * none of that is the case the problem is not in this function :-)
725          ********************************************/
726         FIXME("Depth stencil locking not supported yet\n");
727     } else {
728         /* This path is for normal surfaces, offscreen render targets and everything else that is in a gl texture */
729         TRACE("locking an ordinarary surface\n");
730
731         /* TODO: Make sure that *any* context is active for this thread. It is not important which context that is,
732          * nor that is has any special setup(CTXUSAGE_LOADRESOURCE is fine), but the code below needs a context.
733          * A context is guaranted to be there in a single threaded environment, but not with multithreading
734          */
735         if (0 != This->glDescription.textureName) {
736             /* Now I have to copy thing bits back */
737
738             /* Make sure that a proper texture unit is selected, bind the texture and dirtify the sampler to restore the texture on the next draw */
739             if (GL_SUPPORT(ARB_MULTITEXTURE)) {
740                 ENTER_GL();
741                 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
742                 checkGLcall("glActiveTextureARB");
743                 LEAVE_GL();
744             }
745             IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(0));
746             IWineD3DSurface_PreLoad(iface);
747
748             surface_download_data(This);
749         }
750
751         /* The local copy is now up to date to the opengl one because a full download was done */
752         This->Flags &= ~SFLAG_GLDIRTY;
753     }
754
755 lock_end:
756     if (Flags & (WINED3DLOCK_NO_DIRTY_UPDATE | WINED3DLOCK_READONLY)) {
757         /* Don't dirtify */
758     } else {
759         IWineD3DBaseTexture *pBaseTexture;
760         /**
761          * Dirtify on lock
762          * as seen in msdn docs
763          */
764         IWineD3DSurface_AddDirtyRect(iface, &This->lockedRect);
765
766         /** Dirtify Container if needed */
767         if (WINED3D_OK == IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&pBaseTexture) && pBaseTexture != NULL) {
768             TRACE("Making container dirty\n");
769             IWineD3DBaseTexture_SetDirty(pBaseTexture, TRUE);
770             IWineD3DBaseTexture_Release(pBaseTexture);
771         } else {
772             TRACE("Surface is standalone, no need to dirty the container\n");
773         }
774     }
775
776     TRACE("returning memory@%p, pitch(%d) dirtyfied(%d)\n", pLockedRect->pBits, pLockedRect->Pitch, This->Flags & SFLAG_DIRTY ? 0 : 1);
777     return WINED3D_OK;
778 }
779
780 static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This) {
781     GLint  prev_store;
782     GLint  prev_rasterpos[4];
783     GLint skipBytes = 0;
784     BOOL storechanged = FALSE, memory_allocated = FALSE;
785     GLint fmt, type;
786     BYTE *mem;
787     UINT bpp;
788     UINT pitch = IWineD3DSurface_GetPitch((IWineD3DSurface *) This);    /* target is argb, 4 byte */
789
790     glDisable(GL_TEXTURE_2D);
791     vcheckGLcall("glDisable(GL_TEXTURE_2D)");
792
793     glFlush();
794     vcheckGLcall("glFlush");
795     glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
796     vcheckGLcall("glIntegerv");
797     glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]);
798     vcheckGLcall("glIntegerv");
799     glPixelZoom(1.0, -1.0);
800     vcheckGLcall("glPixelZoom");
801
802     /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
803     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &skipBytes);
804     glPixelStorei(GL_UNPACK_ROW_LENGTH, This->currentDesc.Width);
805
806     glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
807     vcheckGLcall("glRasterPos2f");
808
809     /* Some drivers(radeon dri, others?) don't like exceptions during
810      * glDrawPixels. If the surface is a DIB section, it might be in GDIMode
811      * after ReleaseDC. Reading it will cause an exception, which x11drv will
812      * catch to put the dib section in InSync mode, which leads to a crash
813      * and a blocked x server on my radeon card.
814      *
815      * The following lines read the dib section so it is put in inSync mode
816      * before glDrawPixels is called and the crash is prevented. There won't
817      * be any interfering gdi accesses, because UnlockRect is called from
818      * ReleaseDC, and the app won't use the dc any more afterwards.
819      */
820     if(This->Flags & SFLAG_DIBSECTION) {
821         volatile BYTE read;
822         read = This->resource.allocatedMemory[0];
823     }
824
825     switch (This->resource.format) {
826         /* No special care needed */
827         case WINED3DFMT_A4R4G4B4:
828         case WINED3DFMT_R5G6B5:
829         case WINED3DFMT_A1R5G5B5:
830         case WINED3DFMT_R8G8B8:
831             type = This->glDescription.glType;
832             fmt = This->glDescription.glFormat;
833             mem = This->resource.allocatedMemory;
834             bpp = This->bytesPerPixel;
835             break;
836
837         case WINED3DFMT_X4R4G4B4:
838         {
839             int size;
840             unsigned short *data;
841             data = (unsigned short *)This->resource.allocatedMemory;
842             size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
843             while(size > 0) {
844                 *data |= 0xF000;
845                 data++;
846                 size--;
847             }
848             type = This->glDescription.glType;
849             fmt = This->glDescription.glFormat;
850             mem = This->resource.allocatedMemory;
851             bpp = This->bytesPerPixel;
852         }
853         break;
854
855         case WINED3DFMT_X1R5G5B5:
856         {
857             int size;
858             unsigned short *data;
859             data = (unsigned short *)This->resource.allocatedMemory;
860             size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
861             while(size > 0) {
862                 *data |= 0x8000;
863                 data++;
864                 size--;
865             }
866             type = This->glDescription.glType;
867             fmt = This->glDescription.glFormat;
868             mem = This->resource.allocatedMemory;
869             bpp = This->bytesPerPixel;
870         }
871         break;
872
873         case WINED3DFMT_X8R8G8B8:
874         {
875             /* make sure the X byte is set to alpha on, since it 
876                could be any random value. This fixes the intro movie in Pirates! */
877             int size;
878             unsigned int *data;
879             data = (unsigned int *)This->resource.allocatedMemory;
880             size = (This->lockedRect.bottom - This->lockedRect.top) * (This->lockedRect.right - This->lockedRect.left);
881             while(size > 0) {
882                 *data |= 0xFF000000;
883                 data++;
884                 size--;
885             }
886         }
887         /* Fall through */
888
889         case WINED3DFMT_A8R8G8B8:
890         {
891             glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
892             vcheckGLcall("glPixelStorei");
893             storechanged = TRUE;
894             type = This->glDescription.glType;
895             fmt = This->glDescription.glFormat;
896             mem = This->resource.allocatedMemory;
897             bpp = This->bytesPerPixel;
898         }
899         break;
900
901         case WINED3DFMT_A2R10G10B10:
902         {
903             glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
904             vcheckGLcall("glPixelStorei");
905             storechanged = TRUE;
906             type = This->glDescription.glType;
907             fmt = This->glDescription.glFormat;
908             mem = This->resource.allocatedMemory;
909             bpp = This->bytesPerPixel;
910         }
911         break;
912
913         case WINED3DFMT_P8:
914         {
915             int height = This->glRect.bottom - This->glRect.top;
916             type = GL_UNSIGNED_BYTE;
917             fmt = GL_RGBA;
918
919             mem = HeapAlloc(GetProcessHeap(), 0, This->resource.size * sizeof(DWORD));
920             if(!mem) {
921                 ERR("Out of memory\n");
922                 return;
923             }
924             memory_allocated = TRUE;
925             d3dfmt_convert_surface(This->resource.allocatedMemory,
926                                    mem,
927                                    pitch,
928                                    pitch,
929                                    height,
930                                    pitch * 4,
931                                    CONVERT_PALETTED,
932                                    This);
933             bpp = This->bytesPerPixel * 4;
934             pitch *= 4;
935         }
936         break;
937
938         default:
939             FIXME("Unsupported Format %u in locking func\n", This->resource.format);
940
941             /* Give it a try */
942             type = This->glDescription.glType;
943             fmt = This->glDescription.glFormat;
944             mem = This->resource.allocatedMemory;
945             bpp = This->bytesPerPixel;
946     }
947
948     glDrawPixels(This->lockedRect.right - This->lockedRect.left,
949                  (This->lockedRect.bottom - This->lockedRect.top)-1,
950                  fmt, type,
951                  mem + bpp * This->lockedRect.left + pitch * This->lockedRect.top);
952     checkGLcall("glDrawPixels");
953     glPixelZoom(1.0,1.0);
954     vcheckGLcall("glPixelZoom");
955
956     glRasterPos3iv(&prev_rasterpos[0]);
957     vcheckGLcall("glRasterPos3iv");
958
959     /* Reset to previous pack row length */
960     glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
961     vcheckGLcall("glPixelStorei GL_UNPACK_ROW_LENGTH");
962     if(storechanged) {
963         glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
964         vcheckGLcall("glPixelStorei GL_PACK_SWAP_BYTES");
965     }
966
967     if(memory_allocated) HeapFree(GetProcessHeap(), 0, mem);
968     return;
969 }
970
971 static void flush_to_framebuffer_texture(IWineD3DSurfaceImpl *This) {
972     float glTexCoord[4];
973
974     glTexCoord[0] = (float) This->lockedRect.left   / (float) This->pow2Width; /* left */
975     glTexCoord[1] = (float) This->lockedRect.right  / (float) This->pow2Width; /* right */
976     glTexCoord[2] = (float) This->lockedRect.top    / (float) This->pow2Height; /* top */
977     glTexCoord[3] = (float) This->lockedRect.bottom / (float) This->pow2Height; /* bottom */
978
979     IWineD3DSurface_PreLoad((IWineD3DSurface *) This);
980
981     ENTER_GL();
982
983     glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
984     checkGLcall("glEnable glBindTexture");
985
986     /* No filtering for blts */
987     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
988     checkGLcall("glTexParameteri");
989     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
990     checkGLcall("glTexParameteri");
991
992     /* Start drawing a quad */
993     glBegin(GL_QUADS);
994
995     glColor3d(1.0f, 1.0f, 1.0f);
996     glTexCoord2f(glTexCoord[0], glTexCoord[2]);
997     glVertex3f(This->lockedRect.left, This->lockedRect.top, 0.0);
998
999     glTexCoord2f(glTexCoord[0], glTexCoord[3]);
1000     glVertex3f(This->lockedRect.left, This->lockedRect.bottom, 0.0);
1001
1002     glTexCoord2f(glTexCoord[1], glTexCoord[3]);
1003     glVertex3d(This->lockedRect.right, This->lockedRect.bottom, 0.0);
1004
1005     glTexCoord2f(glTexCoord[1], glTexCoord[2]);
1006     glVertex3f(This->lockedRect.right, This->lockedRect.top, 0.0);
1007
1008     glEnd();
1009     checkGLcall("glEnd");
1010
1011     /* Unbind the texture */
1012     glBindTexture(GL_TEXTURE_2D, 0);
1013     checkGLcall("glEnable glBindTexture");
1014
1015     LEAVE_GL();
1016 }
1017
1018 static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
1019     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1020     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
1021     IWineD3DSwapChainImpl *swapchain = NULL;
1022
1023     if (!(This->Flags & SFLAG_LOCKED)) {
1024         WARN("trying to Unlock an unlocked surf@%p\n", This);
1025         return WINED3DERR_INVALIDCALL;
1026     }
1027
1028     TRACE("(%p) : dirtyfied(%d)\n", This, This->Flags & SFLAG_DIRTY ? 1 : 0);
1029
1030     if (!(This->Flags & SFLAG_DIRTY)) {
1031         TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
1032         goto unlock_end;
1033     }
1034
1035     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
1036     if(swapchain || iface == myDevice->render_targets[0]) {
1037         if(wined3d_settings.rendertargetlock_mode == RTL_DISABLE) {
1038             static BOOL warned = FALSE;
1039             if(!warned) {
1040                 ERR("The application tries to write to the render target, but render target locking is disabled\n");
1041                 warned = TRUE;
1042             }
1043             if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
1044             goto unlock_end;
1045         }
1046
1047         /* Activate the correct context for the render target */
1048         ENTER_GL();
1049         ActivateContext(myDevice, iface, CTXUSAGE_BLIT);
1050
1051         if(!swapchain) {
1052             /* Primary offscreen render target */
1053             TRACE("Offscreen render target\n");
1054             glDrawBuffer(GL_BACK);
1055             checkGLcall("glDrawBuffer(GL_BACK)");
1056         } else {
1057             if(iface == swapchain->frontBuffer) {
1058                 TRACE("Onscreen front buffer\n");
1059                 glDrawBuffer(GL_FRONT);
1060                 checkGLcall("glDrawBuffer(GL_FRONT)");
1061             } else if(iface == swapchain->backBuffer[0]) {
1062                 TRACE("Onscreen back buffer\n");
1063                 glDrawBuffer(GL_BACK);
1064                 checkGLcall("glDrawBuffer(GL_BACK)");
1065             } else {
1066                 FIXME("Unlocking a higher back buffer\n");
1067                 glDrawBuffer(GL_BACK);
1068                 checkGLcall("glDrawBuffer(GL_BACK)");
1069             }
1070             IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
1071         }
1072
1073         switch(wined3d_settings.rendertargetlock_mode) {
1074             case RTL_AUTO:
1075             case RTL_READDRAW:
1076             case RTL_TEXDRAW:
1077                 flush_to_framebuffer_drawpixels(This);
1078                 break;
1079
1080             case RTL_READTEX:
1081             case RTL_TEXTEX:
1082                 flush_to_framebuffer_texture(This);
1083                 break;
1084         }
1085         if(!swapchain || swapchain->backBuffer) {
1086             glDrawBuffer(GL_BACK);
1087             checkGLcall("glDrawBuffer(GL_BACK)");
1088         } else {
1089             glDrawBuffer(GL_FRONT);
1090             checkGLcall("glDrawBuffer(GL_FRONT)");
1091         }
1092         LEAVE_GL();
1093
1094         /** restore clean dirty state */
1095         IWineD3DSurface_CleanDirtyRect(iface);
1096     } else if(iface == myDevice->stencilBufferTarget) {
1097         FIXME("Depth Stencil buffer locking is not implemented\n");
1098     } else {
1099         /* The rest should be a normal texture */
1100         IWineD3DBaseTextureImpl *impl;
1101         /* Check if the texture is bound, if yes dirtify the sampler to force a re-upload of the texture
1102          * Can't load the texture here because PreLoad may destroy and recreate the gl texture, so sampler
1103          * states need resetting
1104          */
1105         if(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&impl) == WINED3D_OK) {
1106             if(impl->baseTexture.bindCount) {
1107                 IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_SAMPLER(impl->baseTexture.sampler));
1108             }
1109             IWineD3DBaseTexture_Release((IWineD3DBaseTexture *) impl);
1110         }
1111     }
1112
1113     unlock_end:
1114     This->Flags &= ~SFLAG_LOCKED;
1115     memset(&This->lockedRect, 0, sizeof(RECT));
1116     return WINED3D_OK;
1117 }
1118
1119 HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
1120     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1121     WINED3DLOCKED_RECT lock;
1122     UINT usage;
1123     BITMAPINFO* b_info;
1124     HDC ddc;
1125     DWORD *masks;
1126     HRESULT hr;
1127     RGBQUAD col[256];
1128     const PixelFormatDesc *formatEntry = getFormatDescEntry(This->resource.format);
1129
1130     TRACE("(%p)->(%p)\n",This,pHDC);
1131
1132     if(This->Flags & SFLAG_USERPTR) {
1133         ERR("Not supported on surfaces with an application-provided surfaces\n");
1134         return DDERR_NODC;
1135     }
1136
1137     /* Give more detailed info for ddraw */
1138     if (This->Flags & SFLAG_DCINUSE)
1139         return DDERR_DCALREADYCREATED;
1140
1141     /* Can't GetDC if the surface is locked */
1142     if (This->Flags & SFLAG_LOCKED)
1143         return WINED3DERR_INVALIDCALL;
1144
1145     memset(&lock, 0, sizeof(lock)); /* To be sure */
1146
1147     /* Create a DIB section if there isn't a hdc yet */
1148     if(!This->hDC) {
1149         int extraline = 0;
1150         SYSTEM_INFO sysInfo;
1151
1152         switch (This->bytesPerPixel) {
1153             case 2:
1154             case 4:
1155                 /* Allocate extra space to store the RGB bit masks. */
1156                 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
1157                 break;
1158
1159             case 3:
1160                 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
1161                 break;
1162
1163             default:
1164                 /* Allocate extra space for a palette. */
1165                 b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1166                                   sizeof(BITMAPINFOHEADER)
1167                                   + sizeof(RGBQUAD)
1168                                   * (1 << (This->bytesPerPixel * 8)));
1169                 break;
1170         }
1171
1172         if (!b_info)
1173             return E_OUTOFMEMORY;
1174
1175         /* Some apps access the surface in via DWORDs, and do not take the necessary care at the end of the
1176          * surface. So we need at least extra 4 bytes at the end of the surface. Check against the page size,
1177          * if the last page used for the surface has at least 4 spare bytes we're safe, otherwise
1178          * add an extra line to the dib section
1179          */
1180         GetSystemInfo(&sysInfo);
1181         if( ((This->resource.size + 3) % sysInfo.dwPageSize) < 4) {
1182             extraline = 1;
1183             TRACE("Adding an extra line to the dib section\n");
1184         }
1185
1186         b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1187         b_info->bmiHeader.biWidth = This->currentDesc.Width;
1188         b_info->bmiHeader.biHeight = -This->currentDesc.Height -extraline;
1189         b_info->bmiHeader.biSizeImage = ( This->currentDesc.Height + extraline) * IWineD3DSurface_GetPitch(iface);
1190         b_info->bmiHeader.biPlanes = 1;
1191         b_info->bmiHeader.biBitCount = This->bytesPerPixel * 8;
1192
1193         b_info->bmiHeader.biXPelsPerMeter = 0;
1194         b_info->bmiHeader.biYPelsPerMeter = 0;
1195         b_info->bmiHeader.biClrUsed = 0;
1196         b_info->bmiHeader.biClrImportant = 0;
1197
1198         /* Get the bit masks */
1199         masks = (DWORD *) &(b_info->bmiColors);
1200         switch (This->resource.format) {
1201             case WINED3DFMT_R8G8B8:
1202                 usage = DIB_RGB_COLORS;
1203                 b_info->bmiHeader.biCompression = BI_RGB;
1204                 break;
1205
1206             case WINED3DFMT_X1R5G5B5:
1207             case WINED3DFMT_A1R5G5B5:
1208             case WINED3DFMT_A4R4G4B4:
1209             case WINED3DFMT_X4R4G4B4:
1210             case WINED3DFMT_R3G3B2:
1211             case WINED3DFMT_A8R3G3B2:
1212             case WINED3DFMT_A2B10G10R10:
1213             case WINED3DFMT_A8B8G8R8:
1214             case WINED3DFMT_X8B8G8R8:
1215             case WINED3DFMT_A2R10G10B10:
1216             case WINED3DFMT_R5G6B5:
1217             case WINED3DFMT_A16B16G16R16:
1218                 usage = 0;
1219                 b_info->bmiHeader.biCompression = BI_BITFIELDS;
1220                 masks[0] = formatEntry->redMask;
1221                 masks[1] = formatEntry->greenMask;
1222                 masks[2] = formatEntry->blueMask;
1223                 break;
1224
1225             default:
1226                 /* Don't know palette */
1227                 b_info->bmiHeader.biCompression = BI_RGB;
1228                 usage = 0;
1229                 break;
1230         }
1231
1232         ddc = GetDC(0);
1233         if (ddc == 0) {
1234             HeapFree(GetProcessHeap(), 0, b_info);
1235             return HRESULT_FROM_WIN32(GetLastError());
1236         }
1237
1238         TRACE("Creating a DIB section with size %dx%dx%d, size=%d\n", b_info->bmiHeader.biWidth, b_info->bmiHeader.biHeight, b_info->bmiHeader.biBitCount, b_info->bmiHeader.biSizeImage);
1239         This->dib.DIBsection = CreateDIBSection(ddc, b_info, usage, &This->dib.bitmap_data, 0 /* Handle */, 0 /* Offset */);
1240         ReleaseDC(0, ddc);
1241
1242         if (!This->dib.DIBsection) {
1243             ERR("CreateDIBSection failed!\n");
1244             HeapFree(GetProcessHeap(), 0, b_info);
1245             return HRESULT_FROM_WIN32(GetLastError());
1246         }
1247
1248         TRACE("DIBSection at : %p\n", This->dib.bitmap_data);
1249
1250         /* copy the existing surface to the dib section */
1251         if(This->resource.allocatedMemory) {
1252             memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, b_info->bmiHeader.biSizeImage);
1253             /* We won't need that any more */
1254             HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
1255         } else {
1256             /* This is to make LockRect read the gl Texture although memory is allocated */
1257             This->Flags |= SFLAG_GLDIRTY;
1258         }
1259
1260         HeapFree(GetProcessHeap(), 0, b_info);
1261
1262         /* Use the dib section from now on */
1263         This->resource.allocatedMemory = This->dib.bitmap_data;
1264
1265         /* Now allocate a HDC */
1266         This->hDC = CreateCompatibleDC(0);
1267         This->dib.holdbitmap = SelectObject(This->hDC, This->dib.DIBsection);
1268         TRACE("using wined3d palette %p\n", This->palette);
1269         SelectPalette(This->hDC,
1270                       This->palette ? This->palette->hpal : 0,
1271                       FALSE);
1272
1273         This->Flags |= SFLAG_DIBSECTION;
1274     }
1275
1276     /* Lock the surface */
1277     hr = IWineD3DSurface_LockRect(iface,
1278                                   &lock,
1279                                   NULL,
1280                                   0);
1281     if(FAILED(hr)) {
1282         ERR("IWineD3DSurface_LockRect failed with hr = %08x\n", hr);
1283         /* keep the dib section */
1284         return hr;
1285     }
1286
1287     if(This->resource.format == WINED3DFMT_P8 ||
1288         This->resource.format == WINED3DFMT_A8P8) {
1289         unsigned int n;
1290         if(This->palette) {
1291             PALETTEENTRY ent[256];
1292
1293             GetPaletteEntries(This->palette->hpal, 0, 256, ent);
1294             for (n=0; n<256; n++) {
1295                 col[n].rgbRed   = ent[n].peRed;
1296                 col[n].rgbGreen = ent[n].peGreen;
1297                 col[n].rgbBlue  = ent[n].peBlue;
1298                 col[n].rgbReserved = 0;
1299             }
1300         } else {
1301             IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1302
1303             for (n=0; n<256; n++) {
1304                 col[n].rgbRed   = device->palettes[device->currentPalette][n].peRed;
1305                 col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
1306                 col[n].rgbBlue  = device->palettes[device->currentPalette][n].peBlue;
1307                 col[n].rgbReserved = 0;
1308             }
1309
1310         }
1311         SetDIBColorTable(This->hDC, 0, 256, col);
1312     }
1313
1314     *pHDC = This->hDC;
1315     TRACE("returning %p\n",*pHDC);
1316     This->Flags |= SFLAG_DCINUSE;
1317
1318     return WINED3D_OK;
1319 }
1320
1321 HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) {
1322     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1323
1324     TRACE("(%p)->(%p)\n",This,hDC);
1325
1326     if (!(This->Flags & SFLAG_DCINUSE))
1327         return D3DERR_INVALIDCALL;
1328
1329     /* we locked first, so unlock now */
1330     IWineD3DSurface_UnlockRect(iface);
1331
1332     This->Flags &= ~SFLAG_DCINUSE;
1333
1334     return WINED3D_OK;
1335 }
1336
1337 /* ******************************************************
1338    IWineD3DSurface Internal (No mapping to directx api) parts follow
1339    ****************************************************** */
1340
1341 HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_texturing, GLenum *format, GLenum *internal, GLenum *type, CONVERT_TYPES *convert, int *target_bpp) {
1342     BOOL colorkey_active = need_alpha_ck && (This->CKeyFlags & DDSD_CKSRCBLT);
1343     const PixelFormatDesc *formatEntry = getFormatDescEntry(This->resource.format);
1344
1345     /* Default values: From the surface */
1346     *format = formatEntry->glFormat;
1347     *internal = formatEntry->glInternal;
1348     *type = formatEntry->glType;
1349     *convert = NO_CONVERSION;
1350     *target_bpp = This->bytesPerPixel;
1351
1352     /* Ok, now look if we have to do any conversion */
1353     switch(This->resource.format) {
1354         case WINED3DFMT_P8:
1355             /* ****************
1356                 Paletted Texture
1357                 **************** */
1358             /* Use conversion when the paletted texture extension is not available, or when it is available make sure it is used
1359              * for texturing as it won't work for calls like glDraw-/glReadPixels and further also use conversion in case of color keying.
1360              */
1361             if(!GL_SUPPORT(EXT_PALETTED_TEXTURE) || colorkey_active || (!use_texturing && GL_SUPPORT(EXT_PALETTED_TEXTURE)) ) {
1362                 *format = GL_RGBA;
1363                 *internal = GL_RGBA;
1364                 *type = GL_UNSIGNED_BYTE;
1365                 *target_bpp = 4;
1366                 if(colorkey_active) {
1367                     *convert = CONVERT_PALETTED_CK;
1368                 } else {
1369                     *convert = CONVERT_PALETTED;
1370                 }
1371             }
1372
1373             break;
1374
1375         case WINED3DFMT_R3G3B2:
1376             /* **********************
1377                 GL_UNSIGNED_BYTE_3_3_2
1378                 ********************** */
1379             if (colorkey_active) {
1380                 /* This texture format will never be used.. So do not care about color keying
1381                     up until the point in time it will be needed :-) */
1382                 FIXME(" ColorKeying not supported in the RGB 332 format !\n");
1383             }
1384             break;
1385
1386         case WINED3DFMT_R5G6B5:
1387             if (colorkey_active) {
1388                 *convert = CONVERT_CK_565;
1389                 *format = GL_RGBA;
1390                 *internal = GL_RGBA;
1391                 *type = GL_UNSIGNED_SHORT_5_5_5_1;
1392             }
1393             break;
1394
1395         case WINED3DFMT_R8G8B8:
1396             if (colorkey_active) {
1397                 *convert = CONVERT_CK_RGB24;
1398                 *format = GL_RGBA;
1399                 *internal = GL_RGBA;
1400                 *type = GL_UNSIGNED_INT_8_8_8_8;
1401                 *target_bpp = 4;
1402             }
1403             break;
1404
1405         case WINED3DFMT_X8R8G8B8:
1406             if (colorkey_active) {
1407                 *convert = CONVERT_RGB32_888;
1408                 *format = GL_RGBA;
1409                 *internal = GL_RGBA;
1410                 *type = GL_UNSIGNED_INT_8_8_8_8;
1411             }
1412             break;
1413
1414         case WINED3DFMT_V8U8:
1415             *convert = CONVERT_V8U8;
1416             *format = GL_BGR;
1417             *internal = GL_RGB8;
1418             *type = GL_BYTE;
1419             *target_bpp = 3;
1420             break;
1421
1422         default:
1423             break;
1424     }
1425
1426     return WINED3D_OK;
1427 }
1428
1429 HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *surf) {
1430     BYTE *source, *dest;
1431     TRACE("(%p)->(%p),(%d,%d,%d,%d,%p)\n", src, dst, pitch, height, outpitch, convert, surf);
1432
1433     switch (convert) {
1434         case NO_CONVERSION:
1435         {
1436             memcpy(dst, src, pitch * height);
1437             break;
1438         }
1439         case CONVERT_PALETTED:
1440         case CONVERT_PALETTED_CK:
1441         {
1442             IWineD3DPaletteImpl* pal = surf->palette;
1443             BYTE table[256][4];
1444             unsigned int i;
1445             unsigned int x, y;
1446
1447             if( pal == NULL) {
1448                 /* TODO: If we are a sublevel, try to get the palette from level 0 */
1449             }
1450
1451             if (pal == NULL) {
1452                 /* Still no palette? Use the device's palette */
1453                 /* Get the surface's palette */
1454                 for (i = 0; i < 256; i++) {
1455                     IWineD3DDeviceImpl *device = surf->resource.wineD3DDevice;
1456
1457                     table[i][0] = device->palettes[device->currentPalette][i].peRed;
1458                     table[i][1] = device->palettes[device->currentPalette][i].peGreen;
1459                     table[i][2] = device->palettes[device->currentPalette][i].peBlue;
1460                     if ((convert == CONVERT_PALETTED_CK) &&
1461                         (i >= surf->SrcBltCKey.dwColorSpaceLowValue) &&
1462                         (i <= surf->SrcBltCKey.dwColorSpaceHighValue)) {
1463                         /* We should maybe here put a more 'neutral' color than the standard bright purple
1464                           one often used by application to prevent the nice purple borders when bi-linear
1465                           filtering is on */
1466                         table[i][3] = 0x00;
1467                     } else {
1468                         table[i][3] = 0xFF;
1469                     }
1470                 }
1471             } else {
1472                 TRACE("Using surface palette %p\n", pal);
1473                 /* Get the surface's palette */
1474                 for (i = 0; i < 256; i++) {
1475                     table[i][0] = pal->palents[i].peRed;
1476                     table[i][1] = pal->palents[i].peGreen;
1477                     table[i][2] = pal->palents[i].peBlue;
1478                     if ((convert == CONVERT_PALETTED_CK) &&
1479                         (i >= surf->SrcBltCKey.dwColorSpaceLowValue) &&
1480                         (i <= surf->SrcBltCKey.dwColorSpaceHighValue)) {
1481                         /* We should maybe here put a more 'neutral' color than the standard bright purple
1482                           one often used by application to prevent the nice purple borders when bi-linear
1483                           filtering is on */
1484                         table[i][3] = 0x00;
1485                     } else {
1486                         table[i][3] = 0xFF;
1487                     }
1488                 }
1489             }
1490
1491             for (y = 0; y < height; y++)
1492             {
1493                 source = src + pitch * y;
1494                 dest = dst + outpitch * y;
1495                 /* This is an 1 bpp format, using the width here is fine */
1496                 for (x = 0; x < width; x++) {
1497                     BYTE color = *source++;
1498                     *dest++ = table[color][0];
1499                     *dest++ = table[color][1];
1500                     *dest++ = table[color][2];
1501                     *dest++ = table[color][3];
1502                 }
1503             }
1504         }
1505         break;
1506
1507         case CONVERT_CK_565:
1508         {
1509             /* Converting the 565 format in 5551 packed to emulate color-keying.
1510
1511               Note : in all these conversion, it would be best to average the averaging
1512                       pixels to get the color of the pixel that will be color-keyed to
1513                       prevent 'color bleeding'. This will be done later on if ever it is
1514                       too visible.
1515
1516               Note2: Nvidia documents say that their driver does not support alpha + color keying
1517                      on the same surface and disables color keying in such a case
1518             */
1519             unsigned int x, y;
1520             WORD *Source;
1521             WORD *Dest;
1522
1523             TRACE("Color keyed 565\n");
1524
1525             for (y = 0; y < height; y++) {
1526                 Source = (WORD *) (src + y * pitch);
1527                 Dest = (WORD *) (dst + y * outpitch);
1528                 for (x = 0; x < width; x++ ) {
1529                     WORD color = *Source++;
1530                     *Dest = ((color & 0xFFC0) | ((color & 0x1F) << 1));
1531                     if ((color < surf->SrcBltCKey.dwColorSpaceLowValue) ||
1532                         (color > surf->SrcBltCKey.dwColorSpaceHighValue)) {
1533                         *Dest |= 0x0001;
1534                     }
1535                     Dest++;
1536                 }
1537             }
1538         }
1539         break;
1540
1541         case CONVERT_V8U8:
1542         {
1543             unsigned int x, y;
1544             short *Source;
1545             char *Dest;
1546             for(y = 0; y < height; y++) {
1547                 Source = (short *) (src + y * pitch);
1548                 Dest = (char *) (dst + y * outpitch);
1549                 for (x = 0; x < width; x++ ) {
1550                     long color = (*Source++);
1551                     Dest[0] = color >> 8;
1552                     Dest[1] = color;
1553                     Dest[2] = 0xff;
1554                     Dest += 3;
1555                 }
1556             }
1557             break;
1558         }
1559
1560         default:
1561             ERR("Unsupported conversation type %d\n", convert);
1562     }
1563     return WINED3D_OK;
1564 }
1565
1566 /* This function is used in case of 8bit paletted textures to upload the palette.
1567    For now it only supports GL_EXT_paletted_texture extension but support for other
1568    extensions like ARB_fragment_program and ATI_fragment_shaders will be added as well.
1569 */
1570 void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES convert) {
1571     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1572     IWineD3DPaletteImpl* pal = This->palette;
1573     BYTE table[256][4];
1574     int i;
1575
1576     if (pal == NULL) {
1577         /* Still no palette? Use the device's palette */
1578         /* Get the surface's palette */
1579         for (i = 0; i < 256; i++) {
1580             IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1581
1582             table[i][0] = device->palettes[device->currentPalette][i].peRed;
1583             table[i][1] = device->palettes[device->currentPalette][i].peGreen;
1584             table[i][2] = device->palettes[device->currentPalette][i].peBlue;
1585             if ((convert == CONVERT_PALETTED_CK) &&
1586                 (i >= This->SrcBltCKey.dwColorSpaceLowValue) &&
1587                 (i <= This->SrcBltCKey.dwColorSpaceHighValue)) {
1588                 /* We should maybe here put a more 'neutral' color than the standard bright purple
1589                    one often used by application to prevent the nice purple borders when bi-linear
1590                    filtering is on */
1591                 table[i][3] = 0x00;
1592             } else {
1593                 table[i][3] = 0xFF;
1594             }
1595         }
1596     } else {
1597         TRACE("Using surface palette %p\n", pal);
1598         /* Get the surface's palette */
1599         for (i = 0; i < 256; i++) {
1600             table[i][0] = pal->palents[i].peRed;
1601             table[i][1] = pal->palents[i].peGreen;
1602             table[i][2] = pal->palents[i].peBlue;
1603             if ((convert == CONVERT_PALETTED_CK) &&
1604                 (i >= This->SrcBltCKey.dwColorSpaceLowValue) &&
1605                 (i <= This->SrcBltCKey.dwColorSpaceHighValue)) {
1606                 /* We should maybe here put a more 'neutral' color than the standard bright purple
1607                    one often used by application to prevent the nice purple borders when bi-linear
1608                    filtering is on */
1609                 table[i][3] = 0x00;
1610             } else {
1611                 table[i][3] = 0xFF;
1612             }
1613         }
1614     }
1615     GL_EXTCALL(glColorTableEXT(GL_TEXTURE_2D,GL_RGBA,256,GL_RGBA,GL_UNSIGNED_BYTE, table));
1616 }
1617
1618 static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
1619     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1620     GLenum format, internal, type;
1621     CONVERT_TYPES convert;
1622     int bpp;
1623     int width, pitch, outpitch;
1624     BYTE *mem;
1625
1626     if (This->Flags & SFLAG_INTEXTURE) {
1627         TRACE("Surface already in texture\n");
1628         return WINED3D_OK;
1629     }
1630     if (This->Flags & SFLAG_DIRTY) {
1631         TRACE("Reloading because surface is dirty\n");
1632     } else if(/* Reload: gl texture has ck, now no ckey is set OR */
1633               ((This->Flags & SFLAG_GLCKEY) && (!(This->CKeyFlags & DDSD_CKSRCBLT))) ||
1634               /* Reload: vice versa  OR */
1635               ((!(This->Flags & SFLAG_GLCKEY)) && (This->CKeyFlags & DDSD_CKSRCBLT)) ||
1636               /* Also reload: Color key is active AND the color key has changed */
1637               ((This->CKeyFlags & DDSD_CKSRCBLT) && (
1638                 (This->glCKey.dwColorSpaceLowValue != This->SrcBltCKey.dwColorSpaceLowValue) ||
1639                 (This->glCKey.dwColorSpaceHighValue != This->SrcBltCKey.dwColorSpaceHighValue)))) {
1640         TRACE("Reloading because of color keying\n");
1641     } else {
1642         TRACE("surface isn't dirty\n");
1643         return WINED3D_OK;
1644     }
1645
1646     This->Flags &= ~SFLAG_DIRTY;
1647
1648     /* Resources are placed in system RAM and do not need to be recreated when a device is lost.
1649     *  These resources are not bound by device size or format restrictions. Because of this,
1650     *  these resources cannot be accessed by the Direct3D device nor set as textures or render targets.
1651     *  However, these resources can always be created, locked, and copied.
1652     */
1653     if (This->resource.pool == WINED3DPOOL_SCRATCH && !(This->Flags & SFLAG_FORCELOAD) )
1654     {
1655         FIXME("(%p) Operation not supported for scratch textures\n",This);
1656         return WINED3DERR_INVALIDCALL;
1657     }
1658
1659     if (This->Flags & SFLAG_INPBUFFER) {
1660         if (This->glDescription.level != 0)
1661             FIXME("Surface in texture is only supported for level 0\n");
1662         else if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8 ||
1663                  This->resource.format == WINED3DFMT_DXT1 || This->resource.format == WINED3DFMT_DXT2 ||
1664                  This->resource.format == WINED3DFMT_DXT3 || This->resource.format == WINED3DFMT_DXT4 ||
1665                  This->resource.format == WINED3DFMT_DXT5)
1666             FIXME("Format %d not supported\n", This->resource.format);
1667         else {
1668             GLint prevRead;
1669
1670             ENTER_GL();
1671
1672             glGetIntegerv(GL_READ_BUFFER, &prevRead);
1673             vcheckGLcall("glGetIntegerv");
1674             glReadBuffer(GL_BACK);
1675             vcheckGLcall("glReadBuffer");
1676
1677             glCopyTexImage2D(This->glDescription.target,
1678                              This->glDescription.level,
1679                              This->glDescription.glFormatInternal,
1680                              0,
1681                              0,
1682                              This->currentDesc.Width,
1683                              This->currentDesc.Height,
1684                              0);
1685
1686             checkGLcall("glCopyTexImage2D");
1687             glReadBuffer(prevRead);
1688             vcheckGLcall("glReadBuffer");
1689
1690             LEAVE_GL();
1691
1692             TRACE("Updating target %d\n", This->glDescription.target);
1693             This->Flags |= SFLAG_INTEXTURE;
1694         }
1695         return WINED3D_OK;
1696     }
1697
1698     if(This->CKeyFlags & DDSD_CKSRCBLT) {
1699         This->Flags |= SFLAG_GLCKEY;
1700         This->glCKey = This->SrcBltCKey;
1701     }
1702     else This->Flags &= ~SFLAG_GLCKEY;
1703
1704     d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp);
1705
1706     /* The width is in 'length' not in bytes */
1707     width = This->currentDesc.Width;
1708     pitch = IWineD3DSurface_GetPitch(iface);
1709
1710     if((convert != NO_CONVERSION) && This->resource.allocatedMemory) {
1711         int height = This->glRect.bottom - This->glRect.top;
1712
1713         /* Stick to the alignment for the converted surface too, makes it easier to load the surface */
1714         outpitch = width * bpp;
1715         outpitch = (outpitch + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
1716
1717         mem = HeapAlloc(GetProcessHeap(), 0, outpitch * height);
1718         if(!mem) {
1719             ERR("Out of memory %d, %d!\n", outpitch, height);
1720             return WINED3DERR_OUTOFVIDEOMEMORY;
1721         }
1722         d3dfmt_convert_surface(This->resource.allocatedMemory, mem, pitch, width, height, outpitch, convert, This);
1723
1724         This->Flags |= SFLAG_CONVERTED;
1725     } else if (This->resource.format == WINED3DFMT_P8 && GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
1726         d3dfmt_p8_upload_palette(iface, convert);
1727         This->Flags &= ~SFLAG_CONVERTED;
1728         mem = This->resource.allocatedMemory;
1729     } else {
1730         This->Flags &= ~SFLAG_CONVERTED;
1731         mem = This->resource.allocatedMemory;
1732     }
1733
1734     /* Make sure the correct pitch is used */
1735     glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
1736
1737     if ((This->Flags & SFLAG_NONPOW2) && !(This->Flags & SFLAG_OVERSIZE)) {
1738         TRACE("non power of two support\n");
1739         surface_allocate_surface(This, internal, This->pow2Width, This->pow2Height, format, type);
1740         if (mem) {
1741             surface_upload_data(This, This->currentDesc.Width, This->currentDesc.Height, format, type, mem);
1742         }
1743     } else {
1744         surface_allocate_surface(This, internal, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type);
1745         if (mem) {
1746             surface_upload_data(This, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type, mem);
1747         }
1748     }
1749
1750     /* Restore the default pitch */
1751     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1752
1753     if (mem != This->resource.allocatedMemory)
1754         HeapFree(GetProcessHeap(), 0, mem);
1755
1756 #if 0
1757     {
1758         static unsigned int gen = 0;
1759         char buffer[4096];
1760         ++gen;
1761         if ((gen % 10) == 0) {
1762             snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, This->glDescription.target, This->glDescription.level, gen);
1763             IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer);
1764         }
1765         /*
1766          * debugging crash code
1767          if (gen == 250) {
1768          void** test = NULL;
1769          *test = 0;
1770          }
1771          */
1772     }
1773 #endif
1774
1775     if (!(This->Flags & SFLAG_DONOTFREE)) {
1776         HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
1777         This->resource.allocatedMemory = NULL;
1778     }
1779
1780     return WINED3D_OK;
1781 }
1782
1783 #include <errno.h>
1784 #include <stdio.h>
1785 HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename) {
1786     FILE* f = NULL;
1787     UINT i, y;
1788     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1789     char *allocatedMemory;
1790     char *textureRow;
1791     IWineD3DSwapChain *swapChain = NULL;
1792     int width, height;
1793     GLuint tmpTexture = 0;
1794     DWORD color;
1795     /*FIXME:
1796     Textures my not be stored in ->allocatedgMemory and a GlTexture
1797     so we should lock the surface before saving a snapshot, or at least check that
1798     */
1799     /* TODO: Compressed texture images can be obtained from the GL in uncompressed form
1800     by calling GetTexImage and in compressed form by calling
1801     GetCompressedTexImageARB.  Queried compressed images can be saved and
1802     later reused by calling CompressedTexImage[123]DARB.  Pre-compressed
1803     texture images do not need to be processed by the GL and should
1804     significantly improve texture loading performance relative to uncompressed
1805     images. */
1806
1807 /* Setup the width and height to be the internal texture width and height. */
1808     width  = This->pow2Width;
1809     height = This->pow2Height;
1810 /* check to see if were a 'virtual' texture e.g. were not a pbuffer of texture were a back buffer*/
1811     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapChain);
1812
1813     if (swapChain || (This->Flags & SFLAG_INPBUFFER)) { /* if were not a real texture then read the back buffer into a real texture*/
1814 /* we don't want to interfere with the back buffer so read the data into a temporary texture and then save the data out of the temporary texture */
1815         GLint prevRead;
1816         ENTER_GL();
1817         FIXME("(%p) This surface needs to be locked before a snapshot can be taken\n", This);
1818         glEnable(GL_TEXTURE_2D);
1819
1820         glGenTextures(1, &tmpTexture);
1821         glBindTexture(GL_TEXTURE_2D, tmpTexture);
1822
1823         glTexImage2D(GL_TEXTURE_2D,
1824                         0,
1825                         GL_RGBA,
1826                         width,
1827                         height,
1828                         0/*border*/,
1829                         GL_RGBA,
1830                         GL_UNSIGNED_INT_8_8_8_8_REV,
1831                         NULL);
1832
1833         glGetIntegerv(GL_READ_BUFFER, &prevRead);
1834         vcheckGLcall("glGetIntegerv");
1835         glReadBuffer(GL_BACK);
1836         vcheckGLcall("glReadBuffer");
1837         glCopyTexImage2D(GL_TEXTURE_2D,
1838                             0,
1839                             GL_RGBA,
1840                             0,
1841                             0,
1842                             width,
1843                             height,
1844                             0);
1845
1846         checkGLcall("glCopyTexImage2D");
1847         glReadBuffer(prevRead);
1848         LEAVE_GL();
1849
1850     } else { /* bind the real texture */
1851         IWineD3DSurface_PreLoad(iface);
1852     }
1853     allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width  * height * 4);
1854     ENTER_GL();
1855     FIXME("Saving texture level %d width %d height %d\n", This->glDescription.level, width, height);
1856     glGetTexImage(GL_TEXTURE_2D,
1857                 This->glDescription.level,
1858                 GL_RGBA,
1859                 GL_UNSIGNED_INT_8_8_8_8_REV,
1860                 allocatedMemory);
1861     checkGLcall("glTexImage2D");
1862     if (tmpTexture) {
1863         glBindTexture(GL_TEXTURE_2D, 0);
1864         glDeleteTextures(1, &tmpTexture);
1865     }
1866     LEAVE_GL();
1867
1868     f = fopen(filename, "w+");
1869     if (NULL == f) {
1870         ERR("opening of %s failed with: %s\n", filename, strerror(errno));
1871         return WINED3DERR_INVALIDCALL;
1872     }
1873 /* Save the dat out to a TGA file because 1: it's an easy raw format, 2: it supports an alpha chanel*/
1874     TRACE("(%p) opened %s with format %s\n", This, filename, debug_d3dformat(This->resource.format));
1875 /* TGA header */
1876     fputc(0,f);
1877     fputc(0,f);
1878     fputc(2,f);
1879     fputc(0,f);
1880     fputc(0,f);
1881     fputc(0,f);
1882     fputc(0,f);
1883     fputc(0,f);
1884     fputc(0,f);
1885     fputc(0,f);
1886     fputc(0,f);
1887     fputc(0,f);
1888 /* short width*/
1889     fwrite(&width,2,1,f);
1890 /* short height */
1891     fwrite(&height,2,1,f);
1892 /* format rgba */
1893     fputc(0x20,f);
1894     fputc(0x28,f);
1895 /* raw data */
1896     /* if  the data is upside down if we've fetched it from a back buffer, so it needs flipping again to make it the correct way up*/
1897     if(swapChain)
1898         textureRow = allocatedMemory + (width * (height - 1) *4);
1899     else
1900         textureRow = allocatedMemory;
1901     for (y = 0 ; y < height; y++) {
1902         for (i = 0; i < width;  i++) {
1903             color = *((DWORD*)textureRow);
1904             fputc((color >> 16) & 0xFF, f); /* B */
1905             fputc((color >>  8) & 0xFF, f); /* G */
1906             fputc((color >>  0) & 0xFF, f); /* R */
1907             fputc((color >> 24) & 0xFF, f); /* A */
1908             textureRow += 4;
1909         }
1910         /* take two rows of the pointer to the texture memory */
1911         if(swapChain)
1912             (textureRow-= width << 3);
1913
1914     }
1915     TRACE("Closing file\n");
1916     fclose(f);
1917
1918     if(swapChain) {
1919         IWineD3DSwapChain_Release(swapChain);
1920     }
1921     HeapFree(GetProcessHeap(), 0, allocatedMemory);
1922     return WINED3D_OK;
1923 }
1924
1925 HRESULT WINAPI IWineD3DSurfaceImpl_CleanDirtyRect(IWineD3DSurface *iface) {
1926     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1927     This->Flags &= ~SFLAG_DIRTY;
1928     This->dirtyRect.left   = This->currentDesc.Width;
1929     This->dirtyRect.top    = This->currentDesc.Height;
1930     This->dirtyRect.right  = 0;
1931     This->dirtyRect.bottom = 0;
1932     TRACE("(%p) : Dirty?%d, Rect:(%d,%d,%d,%d)\n", This, This->Flags & SFLAG_DIRTY ? 1 : 0, This->dirtyRect.left,
1933           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1934     return WINED3D_OK;
1935 }
1936
1937 /**
1938  *   Slightly inefficient way to handle multiple dirty rects but it works :)
1939  */
1940 extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) {
1941     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1942     IWineD3DBaseTexture *baseTexture = NULL;
1943     This->Flags |= SFLAG_DIRTY;
1944     if (NULL != pDirtyRect) {
1945         This->dirtyRect.left   = min(This->dirtyRect.left,   pDirtyRect->left);
1946         This->dirtyRect.top    = min(This->dirtyRect.top,    pDirtyRect->top);
1947         This->dirtyRect.right  = max(This->dirtyRect.right,  pDirtyRect->right);
1948         This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
1949     } else {
1950         This->dirtyRect.left   = 0;
1951         This->dirtyRect.top    = 0;
1952         This->dirtyRect.right  = This->currentDesc.Width;
1953         This->dirtyRect.bottom = This->currentDesc.Height;
1954     }
1955     TRACE("(%p) : Dirty?%d, Rect:(%d,%d,%d,%d)\n", This, This->Flags & SFLAG_DIRTY, This->dirtyRect.left,
1956           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
1957     /* if the container is a basetexture then mark it dirty. */
1958     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
1959         TRACE("Passing to conatiner\n");
1960         IWineD3DBaseTexture_SetDirty(baseTexture, TRUE);
1961         IWineD3DBaseTexture_Release(baseTexture);
1962     }
1963     return WINED3D_OK;
1964 }
1965
1966 HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) {
1967     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1968
1969     TRACE("This %p, container %p\n", This, container);
1970
1971     /* We can't keep a reference to the container, since the container already keeps a reference to us. */
1972
1973     TRACE("Setting container to %p from %p\n", container, This->container);
1974     This->container = container;
1975
1976     return WINED3D_OK;
1977 }
1978
1979 HRESULT WINAPI IWineD3DSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
1980     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1981     const PixelFormatDesc *formatEntry = getFormatDescEntry(format);
1982
1983     if (This->resource.format != WINED3DFMT_UNKNOWN) {
1984         FIXME("(%p) : The foramt of the surface must be WINED3DFORMAT_UNKNOWN\n", This);
1985         return WINED3DERR_INVALIDCALL;
1986     }
1987
1988     TRACE("(%p) : Setting texture foramt to (%d,%s)\n", This, format, debug_d3dformat(format));
1989     if (format == WINED3DFMT_UNKNOWN) {
1990         This->resource.size = 0;
1991     } else if (format == WINED3DFMT_DXT1) {
1992         /* DXT1 is half byte per pixel */
1993         This->resource.size = ((max(This->pow2Width, 4) * formatEntry->bpp) * max(This->pow2Height, 4)) >> 1;
1994
1995     } else if (format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3 ||
1996                format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5) {
1997         This->resource.size = ((max(This->pow2Width, 4) * formatEntry->bpp) * max(This->pow2Height, 4));
1998     } else {
1999         This->resource.size = ((This->pow2Width * formatEntry->bpp) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
2000         This->resource.size *= This->pow2Height;
2001     }
2002
2003
2004     /* Setup some glformat defaults */
2005     This->glDescription.glFormat         = formatEntry->glFormat;
2006     This->glDescription.glFormatInternal = formatEntry->glInternal;
2007     This->glDescription.glType           = formatEntry->glType;
2008
2009     if (format != WINED3DFMT_UNKNOWN) {
2010         This->bytesPerPixel = formatEntry->bpp;
2011     } else {
2012         This->bytesPerPixel = 0;
2013     }
2014
2015     This->Flags |= (WINED3DFMT_D16_LOCKABLE == format) ? SFLAG_LOCKABLE : 0;
2016
2017     This->resource.format = format;
2018
2019     TRACE("(%p) : Size %d, bytesPerPixel %d, glFormat %d, glFotmatInternal %d, glType %d\n", This, This->resource.size, This->bytesPerPixel, This->glDescription.glFormat, This->glDescription.glFormatInternal, This->glDescription.glType);
2020
2021     return WINED3D_OK;
2022 }
2023
2024 HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) {
2025     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2026
2027     /* Render targets depend on their hdc, and we can't create a hdc on a user pointer */
2028     if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
2029         ERR("Not supported on render targets\n");
2030         return WINED3DERR_INVALIDCALL;
2031     }
2032
2033     if(This->Flags & (SFLAG_LOCKED | SFLAG_DCINUSE)) {
2034         WARN("Surface is locked or the HDC is in use\n");
2035         return WINED3DERR_INVALIDCALL;
2036     }
2037
2038     if(Mem && Mem != This->resource.allocatedMemory) {
2039
2040         /* Do I have to copy the old surface content? */
2041         if(This->Flags & SFLAG_DIBSECTION) {
2042                 /* Release the DC. No need to hold the critical section for the update
2043                  * Thread because this thread runs only on front buffers, but this method
2044                  * fails for render targets in the check above.
2045                  */
2046                 SelectObject(This->hDC, This->dib.holdbitmap);
2047                 DeleteDC(This->hDC);
2048                 /* Release the DIB section */
2049                 DeleteObject(This->dib.DIBsection);
2050                 This->dib.bitmap_data = NULL;
2051                 This->resource.allocatedMemory = NULL;
2052                 This->hDC = NULL;
2053                 This->Flags &= ~SFLAG_DIBSECTION;
2054         } else if(!(This->Flags & SFLAG_USERPTR)) {
2055             HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
2056         }
2057         This->resource.allocatedMemory = Mem;
2058         This->Flags |= SFLAG_USERPTR;
2059     } else if(This->Flags & SFLAG_USERPTR) {
2060         /* Lockrect and GetDC will re-create the dib section and allocated memory */
2061         This->resource.allocatedMemory = NULL;
2062         This->Flags &= ~SFLAG_USERPTR;
2063     }
2064     return WINED3D_OK;
2065 }
2066
2067 /* TODO: replace this function with context management routines */
2068 HRESULT WINAPI IWineD3DSurfaceImpl_SetPBufferState(IWineD3DSurface *iface, BOOL inPBuffer, BOOL  inTexture) {
2069     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2070
2071     if(inPBuffer) {
2072         This->Flags |= SFLAG_INPBUFFER;
2073     } else {
2074         This->Flags &= ~SFLAG_INPBUFFER;
2075     }
2076
2077     if(inTexture) {
2078         This->Flags |= SFLAG_INTEXTURE;
2079     } else {
2080         This->Flags &= ~SFLAG_INTEXTURE;
2081     }
2082
2083     return WINED3D_OK;
2084 }
2085
2086 static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DSurface *override, DWORD Flags) {
2087     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2088     IWineD3DDevice *D3D = (IWineD3DDevice *) This->resource.wineD3DDevice;
2089     TRACE("(%p)->(%p,%x)\n", This, override, Flags);
2090
2091     /* Flipping is only supported on RenderTargets */
2092     if( !(This->resource.usage & WINED3DUSAGE_RENDERTARGET) ) return DDERR_NOTFLIPPABLE;
2093
2094     if(override) {
2095         /* DDraw sets this for the X11 surfaces, so don't confuse the user 
2096          * FIXME("(%p) Target override is not supported by now\n", This);
2097          * Additionally, it isn't really possible to support triple-buffering
2098          * properly on opengl at all
2099          */
2100     }
2101
2102     /* Flipping a OpenGL surface -> Use WineD3DDevice::Present */
2103     return IWineD3DDevice_Present(D3D, NULL, NULL, 0, NULL);
2104 }
2105
2106 /* Does a direct frame buffer -> texture copy. Stretching is done
2107  * with single pixel copy calls
2108  */
2109 static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3DSurface *SrcSurface, IWineD3DSwapChainImpl *swapchain, WINED3DRECT *srect, WINED3DRECT *drect, BOOL upsidedown) {
2110     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
2111     float xrel, yrel;
2112     UINT row;
2113     BOOL warned = FALSE; /* deliberately not static */
2114     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2115
2116     ENTER_GL();
2117
2118     ActivateContext(myDevice, SrcSurface, CTXUSAGE_BLIT);
2119
2120     /* Bind the target texture */
2121     glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
2122     checkGLcall("glBindTexture");
2123     if(!swapchain || (swapchain->backBuffer && SrcSurface == swapchain->backBuffer[0])) {
2124         glReadBuffer(GL_BACK);
2125     } else {
2126         glReadBuffer(GL_FRONT);
2127     }
2128     checkGLcall("glReadBuffer");
2129
2130     xrel = (float) (srect->x2 - srect->x1) / (float) (drect->x2 - drect->x1);
2131     yrel = (float) (srect->y2 - srect->y1) / (float) (drect->y2 - drect->y1);
2132
2133     if( (xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) {
2134         FIXME("Doing a pixel by pixel copy from the framebuffer to a texture, expect major performance issues\n");
2135     }
2136
2137     if(upsidedown &&
2138        !((xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) &&
2139        !((yrel - 1.0 < -eps) || (yrel - 1.0 > eps))) {
2140         /* Upside down copy without stretching is nice, one glCopyTexSubImage call will do */
2141
2142         glCopyTexSubImage2D(This->glDescription.target,
2143                             This->glDescription.level,
2144                             drect->x1, drect->y1, /* xoffset, yoffset */
2145                             srect->x1, Src->currentDesc.Height - srect->y2,
2146                             drect->x2 - drect->x1, drect->y2 - drect->y1);
2147     } else {
2148         UINT yoffset = Src->currentDesc.Height - srect->y1 + drect->y1 - 1;
2149         /* I have to process this row by row to swap the image,
2150          * otherwise it would be upside down, so streching in y direction
2151          * doesn't cost extra time
2152          *
2153          * However, streching in x direction can be avoided if not necessary
2154          */
2155         for(row = drect->y1; row < drect->y2; row++) {
2156             if( (xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) {
2157                 /* Well, that stuff works, but it's very slow.
2158                  * find a better way instead
2159                  */
2160                 UINT col;
2161
2162                 if(!warned) {
2163                     warned = TRUE;
2164                     FIXME("Doing a pixel by pixel render target -> texture copy, expect performance issues\n");
2165                 }
2166
2167                 for(col = drect->x1; col < drect->x2; col++) {
2168                     glCopyTexSubImage2D(This->glDescription.target,
2169                                         This->glDescription.level,
2170                                         drect->x1 + col, row, /* xoffset, yoffset */
2171                                         srect->x1 + col * xrel, yoffset - (int) (row * yrel),
2172                                         1, 1);
2173                 }
2174             } else {
2175                 glCopyTexSubImage2D(This->glDescription.target,
2176                                     This->glDescription.level,
2177                                     drect->x1, row, /* xoffset, yoffset */
2178                                     srect->x1, yoffset - (int) (row * yrel),
2179                                     drect->x2-drect->x1, 1);
2180             }
2181         }
2182     }
2183
2184     vcheckGLcall("glCopyTexSubImage2D");
2185     LEAVE_GL();
2186 }
2187
2188 /* Uses the hardware to stretch and flip the image */
2189 static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWineD3DSurface *SrcSurface, IWineD3DSwapChainImpl *swapchain, WINED3DRECT *srect, WINED3DRECT *drect, BOOL upsidedown) {
2190     GLuint backup, src;
2191     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
2192     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2193     float left, right, top, bottom; /* Texture coordinates */
2194     UINT fbwidth = Src->currentDesc.Width;
2195     UINT fbheight = Src->currentDesc.Height;
2196
2197     TRACE("Using hwstretch blit\n");
2198     /* Activate the Proper context for reading from the source surface, set it up for blitting */
2199     ENTER_GL();
2200     ActivateContext(myDevice, SrcSurface, CTXUSAGE_BLIT);
2201
2202     /* Backup the back buffer and copy the source buffer into a texture to draw an upside down stretched quad. If
2203      * we are reading from the back buffer, the backup can be used as source texture
2204      */
2205     glGenTextures(1, &backup);
2206     checkGLcall("glGenTextures(1, &backup)");
2207     glBindTexture(GL_TEXTURE_2D, backup);
2208     checkGLcall("glBindTexture(GL_TEXTURE_2D, backup)");
2209
2210     glReadBuffer(GL_BACK);
2211     checkGLcall("glReadBuffer(GL_BACK)");
2212
2213     /* TODO: Only back up the part that will be overwritten */
2214     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Src->pow2Width, Src->pow2Height, 0,
2215                  GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2216     checkGLcall("glTexImage2D");
2217
2218     glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
2219                         0, 0 /* read offsets */,
2220                         0, 0,
2221                         fbwidth,
2222                         fbheight);
2223
2224     checkGLcall("glCopyTexSubImage2D");
2225
2226     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2227     checkGLcall("glTexParameteri");
2228     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2229     checkGLcall("glTexParameteri");
2230
2231     if(!swapchain || (IWineD3DSurface *) This == swapchain->backBuffer[0]) {
2232         src = backup;
2233     } else {
2234         glReadBuffer(GL_FRONT);
2235         checkGLcall("glReadBuffer(GL_FRONT)");
2236
2237         glGenTextures(1, &src);
2238         checkGLcall("glGenTextures(1, &src)");
2239         glBindTexture(GL_TEXTURE_2D, src);
2240         checkGLcall("glBindTexture(GL_TEXTURE_2D, src)");
2241
2242         /* TODO: Only copy the part that will be read. Use srect->x1, srect->y2 as origin, but with the width watch
2243          * out for power of 2 sizes
2244          */
2245         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Src->pow2Width, Src->pow2Height, 0,
2246                     GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2247         checkGLcall("glTexImage2D");
2248         glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
2249                             0, 0 /* read offsets */,
2250                             0, 0,
2251                             fbwidth,
2252                             fbheight);
2253
2254         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2255         checkGLcall("glTexParameteri");
2256         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2257         checkGLcall("glTexParameteri");
2258
2259         glReadBuffer(GL_BACK);
2260         checkGLcall("glReadBuffer(GL_BACK)");
2261     }
2262     checkGLcall("glEnd and previous");
2263
2264     left = (float) srect->x1 / (float) Src->pow2Width;
2265     right = (float) srect->x2 / (float) Src->pow2Width;
2266
2267     if(upsidedown) {
2268         top = (float) (Src->currentDesc.Height - srect->y1) / (float) Src->pow2Height;
2269         bottom = (float) (Src->currentDesc.Height - srect->y2) / (float) Src->pow2Height;
2270     } else {
2271         top = (float) (Src->currentDesc.Height - srect->y2) / (float) Src->pow2Height;
2272         bottom = (float) (Src->currentDesc.Height - srect->y1) / (float) Src->pow2Height;
2273     }
2274
2275     /* draw the source texture stretched and upside down. The correct surface is bound already */
2276     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
2277     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
2278
2279     glBegin(GL_QUADS);
2280         /* bottom left */
2281         glTexCoord2f(left, bottom);
2282         glVertex2i(0, fbheight);
2283
2284         /* top left */
2285         glTexCoord2f(left, top);
2286         glVertex2i(0, fbheight - drect->y2 - drect->y1);
2287
2288         /* top right */
2289         glTexCoord2f(right, top);
2290         glVertex2i(drect->x2 - drect->x1, fbheight - drect->y2 - drect->y1);
2291
2292         /* bottom right */
2293         glTexCoord2f(right, bottom);
2294         glVertex2i(drect->x2 - drect->x1, fbheight);
2295     glEnd();
2296     checkGLcall("glEnd and previous");
2297
2298     /* Now read the stretched and upside down image into the destination texture */
2299     glBindTexture(This->glDescription.target, This->glDescription.textureName);
2300     checkGLcall("glBindTexture");
2301     glCopyTexSubImage2D(This->glDescription.target,
2302                         0,
2303                         drect->x1, drect->y1, /* xoffset, yoffset */
2304                         0, 0, /* We blitted the image to the origin */
2305                         drect->x2 - drect->x1, drect->y2 - drect->y1);
2306     checkGLcall("glCopyTexSubImage2D");
2307
2308     /* Write the back buffer backup back */
2309     glBindTexture(GL_TEXTURE_2D, backup);
2310     checkGLcall("glBindTexture(GL_TEXTURE_2D, backup)");
2311
2312     glBegin(GL_QUADS);
2313         /* top left */
2314         glTexCoord2f(0.0, (float) fbheight / (float) Src->pow2Height);
2315         glVertex2i(0, 0);
2316
2317         /* bottom left */
2318         glTexCoord2f(0.0, 0.0);
2319         glVertex2i(0, fbheight);
2320
2321         /* bottom right */
2322         glTexCoord2f((float) fbwidth / (float) Src->pow2Width, 0.0);
2323         glVertex2i(fbwidth, Src->currentDesc.Height);
2324
2325         /* top right */
2326         glTexCoord2f((float) fbwidth / (float) Src->pow2Width, (float) fbheight / (float) Src->pow2Height);
2327         glVertex2i(fbwidth, 0);
2328     glEnd();
2329
2330     /* Cleanup */
2331     if(src != backup) {
2332         glDeleteTextures(1, &src);
2333         checkGLcall("glDeleteTextures(1, &src)");
2334     }
2335     glDeleteTextures(1, &backup);
2336     checkGLcall("glDeleteTextures(1, &backup)");
2337     LEAVE_GL();
2338 }
2339
2340 /* Not called from the VTable */
2341 static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
2342     WINED3DRECT rect;
2343     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
2344     IWineD3DSwapChainImpl *srcSwapchain = NULL, *dstSwapchain = NULL;
2345     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2346     BOOL SrcOK = TRUE;
2347
2348     TRACE("(%p)->(%p,%p,%p,%08x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2349
2350     /* Get the swapchain. One of the surfaces has to be a primary surface */
2351     IWineD3DSurface_GetContainer( (IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&dstSwapchain);
2352     if(dstSwapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) dstSwapchain);
2353     if(Src) {
2354         IWineD3DSurface_GetContainer( (IWineD3DSurface *) Src, &IID_IWineD3DSwapChain, (void **)&srcSwapchain);
2355         if(srcSwapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) srcSwapchain);
2356     }
2357
2358     /* Early sort out of cases where no render target is used */
2359     if(!dstSwapchain && !srcSwapchain &&
2360         SrcSurface != myDevice->render_targets[0] && This != (IWineD3DSurfaceImpl *) myDevice->render_targets[0]) {
2361         TRACE("No surface is render target, not using hardware blit. Src = %p, dst = %p\n", Src, This);
2362         return WINED3DERR_INVALIDCALL;
2363     }
2364
2365     /* No destination color keying supported */
2366     if(Flags & (DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE)) {
2367         /* Can we support that with glBlendFunc if blitting to the frame buffer? */
2368         TRACE("Destination color key not supported in accelerated Blit, falling back to software\n");
2369         return WINED3DERR_INVALIDCALL;
2370     }
2371
2372     if (DestRect) {
2373         rect.x1 = DestRect->left;
2374         rect.y1 = DestRect->top;
2375         rect.x2 = DestRect->right;
2376         rect.y2 = DestRect->bottom;
2377     } else {
2378         rect.x1 = 0;
2379         rect.y1 = 0;
2380         rect.x2 = This->currentDesc.Width;
2381         rect.y2 = This->currentDesc.Height;
2382     }
2383
2384     /* The only case where both surfaces on a swapchain are supported is a back buffer -> front buffer blit on the same swapchain */
2385     if(dstSwapchain && dstSwapchain == srcSwapchain) {
2386         /* Half-life does a Blt from the back buffer to the front buffer,
2387          * Full surface size, no flags... Use present instead
2388          */
2389
2390         /* Check rects - IWineD3DDevice_Present doesn't handle them */
2391         if( SrcRect ) {
2392             if( (SrcRect->left == 0) && (SrcRect->top == 0) &&
2393                 (SrcRect->right == Src->currentDesc.Width) && (SrcRect->bottom == Src->currentDesc.Height) ) {
2394                 SrcOK = TRUE;
2395             }
2396         } else {
2397             SrcOK = TRUE;
2398         }
2399
2400         /* Check the Destination rect and the surface sizes */
2401         if(SrcOK &&
2402            (rect.x1 == 0) && (rect.y1 == 0) &&
2403            (rect.x2 ==  This->currentDesc.Width) && (rect.y2 == This->currentDesc.Height) &&
2404            (This->currentDesc.Width == Src->currentDesc.Width) &&
2405            (This->currentDesc.Height == Src->currentDesc.Height)) {
2406             /* These flags are unimportant for the flag check, remove them */
2407
2408             if((Flags & ~(DDBLT_DONOTWAIT | DDBLT_WAIT)) == 0) {
2409                 if( dstSwapchain->backBuffer && ((IWineD3DSurface *) This == dstSwapchain->frontBuffer) &&
2410                     SrcSurface == dstSwapchain->backBuffer[0] ) {
2411
2412                     D3DSWAPEFFECT orig_swap = dstSwapchain->presentParms.SwapEffect;
2413
2414                     /* The idea behind this is that a glReadPixels and a glDrawPixels call
2415                      * take very long, while a flip is fast.
2416                      * This applies to Half-Life, which does such Blts every time it finished
2417                      * a frame, and to Prince of Persia 3D, which uses this to draw at least the main
2418                      * menu. This is also used by all apps when they do windowed rendering
2419                      *
2420                      * The problem is that flipping is not really the same as copying. After a
2421                      * Blt the front buffer is a copy of the back buffer, and the back buffer is
2422                      * untouched. Therefore it's necessary to override the swap effect
2423                      * and to set it back after the flip.
2424                      */
2425
2426                     dstSwapchain->presentParms.SwapEffect = WINED3DSWAPEFFECT_COPY;
2427
2428                     TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n");
2429                     IWineD3DDevice_Present((IWineD3DDevice *) This->resource.wineD3DDevice,
2430                                             NULL, NULL, 0, NULL);
2431
2432                     dstSwapchain->presentParms.SwapEffect = orig_swap;
2433
2434                     return WINED3D_OK;
2435                 }
2436             }
2437         }
2438
2439         TRACE("Unsupported blit between buffers on the same swapchain\n");
2440         return WINED3DERR_INVALIDCALL;
2441     } else if((dstSwapchain || This == (IWineD3DSurfaceImpl *) myDevice->render_targets[0]) &&
2442               (srcSwapchain || SrcSurface == myDevice->render_targets[0]) ) {
2443         ERR("Can't perform hardware blit between 2 different swapchains, falling back to software\n");
2444         return WINED3DERR_INVALIDCALL;
2445     }
2446
2447     if(srcSwapchain || SrcSurface == myDevice->render_targets[0]) {
2448         /* Blit from render target to texture */
2449         WINED3DRECT srect;
2450         BOOL upsideDown, stretchx;
2451
2452         if(Flags & (DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE)) {
2453             TRACE("Color keying not supported by frame buffer to texture blit\n");
2454             return WINED3DERR_INVALIDCALL;
2455             /* Destination color key is checked above */
2456         }
2457
2458         /* Call preload for the surface to make sure it isn't dirty */
2459         IWineD3DSurface_PreLoad((IWineD3DSurface *) This);
2460
2461         /* Make sure that the top pixel is always above the bottom pixel, and keep a seperate upside down flag
2462             * glCopyTexSubImage is a bit picky about the parameters we pass to it
2463             */
2464         if(SrcRect) {
2465             if(SrcRect->top < SrcRect->bottom) {
2466                 srect.y1 = SrcRect->top;
2467                 srect.y2 = SrcRect->bottom;
2468                 upsideDown = FALSE;
2469             } else {
2470                 srect.y1 = SrcRect->bottom;
2471                 srect.y2 = SrcRect->top;
2472                 upsideDown = TRUE;
2473             }
2474             srect.x1 = SrcRect->left;
2475             srect.x2 = SrcRect->right;
2476         } else {
2477             srect.x1 = 0;
2478             srect.y1 = 0;
2479             srect.x2 = Src->currentDesc.Width;
2480             srect.y2 = Src->currentDesc.Height;
2481             upsideDown = FALSE;
2482         }
2483         if(rect.x1 > rect.x2) {
2484             UINT tmp = rect.x2;
2485             rect.x2 = rect.x1;
2486             rect.x1 = tmp;
2487             upsideDown = !upsideDown;
2488         }
2489
2490         if(rect.x2 - rect.x1 != srect.x2 - srect.x1) {
2491             stretchx = TRUE;
2492         } else {
2493             stretchx = FALSE;
2494         }
2495
2496         /* Blt is a pretty powerful call, while glCopyTexSubImage2D is not. glCopyTexSubImage cannot
2497          * flip the image nor scale it. If GL_EXT_framebuffer_blit is available it can be used(hopefully,
2498          * not implemented by now). Otherwise:
2499          *
2500          * -> If the app asks for a unscaled, upside down copy, just perform one glCopyTexSubImage2D call
2501          * -> If the app wants a image width an unscaled width, copy it line per line
2502          * -> If the app wants a image that is scaled on the x axis, and the destination rectangle is smaller
2503          *    than the frame buffer, draw an upside down scaled image onto the fb, read it back and restore the
2504          *    back buffer. This is slower than reading line per line, thus not used for flipping
2505          * -> If the app wants a scaled image with a dest rect that is bigger than the fb, it has to be copied
2506          *    pixel by pixel
2507          */
2508         if(FALSE /* GL_SUPPORT(EXT_FRAMEBUFFER_BLIT) */) {
2509             TRACE("Using GL_EXT_framebuffer_blit for copying\n");
2510         } else if((!stretchx) || rect.x2 - rect.x1 > Src->currentDesc.Width ||
2511                                     rect.y2 - rect.y1 > Src->currentDesc.Height) {
2512             TRACE("No stretching in x direction, using direct framebuffer -> texture copy\n");
2513             fb_copy_to_texture_direct(This, SrcSurface, srcSwapchain, &srect, &rect, upsideDown);
2514         } else {
2515             TRACE("Using hardware stretching to flip / stretch the texture\n");
2516             fb_copy_to_texture_hwstretch(This, SrcSurface, srcSwapchain, &srect, &rect, upsideDown);
2517         }
2518
2519         if(!(This->Flags & SFLAG_DONOTFREE)) {
2520             HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
2521             This->resource.allocatedMemory = NULL;
2522         } else {
2523             This->Flags |= SFLAG_GLDIRTY;
2524         }
2525
2526         return WINED3D_OK;
2527     } else if(Src) {
2528         /* Blit from offscreen surface to render target */
2529         float glTexCoord[4];
2530         DWORD oldCKeyFlags = Src->CKeyFlags;
2531         DDCOLORKEY oldBltCKey = This->SrcBltCKey;
2532         RECT SourceRectangle;
2533         GLint oldDraw;
2534
2535         TRACE("Blt from surface %p to rendertarget %p\n", Src, This);
2536
2537         if(SrcRect) {
2538             SourceRectangle.left = SrcRect->left;
2539             SourceRectangle.right = SrcRect->right;
2540             SourceRectangle.top = SrcRect->top;
2541             SourceRectangle.bottom = SrcRect->bottom;
2542         } else {
2543             SourceRectangle.left = 0;
2544             SourceRectangle.right = Src->currentDesc.Width;
2545             SourceRectangle.top = 0;
2546             SourceRectangle.bottom = Src->currentDesc.Height;
2547         }
2548
2549         if(!CalculateTexRect(Src, &SourceRectangle, glTexCoord)) {
2550             /* Fall back to software */
2551             WARN("(%p) Source texture area (%d,%d)-(%d,%d) is too big\n", Src,
2552                     SourceRectangle.left, SourceRectangle.top,
2553                     SourceRectangle.right, SourceRectangle.bottom);
2554             return WINED3DERR_INVALIDCALL;
2555         }
2556
2557         /* Color keying: Check if we have to do a color keyed blt,
2558          * and if not check if a color key is activated.
2559          *
2560          * Just modify the color keying parameters in the surface and restore them afterwards
2561          * The surface keeps track of the color key last used to load the opengl surface.
2562          * PreLoad will catch the change to the flags and color key and reload if neccessary.
2563          */
2564         if(Flags & DDBLT_KEYSRC) {
2565             /* Use color key from surface */
2566         } else if(Flags & DDBLT_KEYSRCOVERRIDE) {
2567             /* Use color key from DDBltFx */
2568             Src->CKeyFlags |= DDSD_CKSRCBLT;
2569             This->SrcBltCKey = DDBltFx->ddckSrcColorkey;
2570         } else {
2571             /* Do not use color key */
2572             Src->CKeyFlags &= ~DDSD_CKSRCBLT;
2573         }
2574
2575         /* Now load the surface */
2576         IWineD3DSurface_PreLoad((IWineD3DSurface *) Src);
2577
2578         ENTER_GL();
2579
2580         /* Activate the destination context, set it up for blitting */
2581         ActivateContext(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT);
2582
2583         glGetIntegerv(GL_DRAW_BUFFER, &oldDraw);
2584         if(This == (IWineD3DSurfaceImpl *) dstSwapchain->frontBuffer) {
2585             TRACE("Drawing to front buffer\n");
2586             glDrawBuffer(GL_FRONT);
2587             checkGLcall("glDrawBuffer GL_FRONT");
2588         }
2589
2590         /* Bind the texture */
2591         glBindTexture(GL_TEXTURE_2D, Src->glDescription.textureName);
2592         checkGLcall("glBindTexture");
2593
2594         /* No filtering for blts */
2595         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2596                         GL_NEAREST);
2597         checkGLcall("glTexParameteri");
2598         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2599                         GL_NEAREST);
2600         checkGLcall("glTexParameteri");
2601         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
2602         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
2603         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2604         checkGLcall("glTexEnvi");
2605
2606         /* This is for color keying */
2607         if(Flags & (DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE)) {
2608             glEnable(GL_ALPHA_TEST);
2609             checkGLcall("glEnable GL_ALPHA_TEST");
2610             glAlphaFunc(GL_NOTEQUAL, 0.0);
2611             checkGLcall("glAlphaFunc\n");
2612         } else {
2613             glDisable(GL_ALPHA_TEST);
2614             checkGLcall("glDisable GL_ALPHA_TEST");
2615         }
2616
2617         /* Draw a textured quad
2618             */
2619         glBegin(GL_QUADS);
2620
2621         glColor3d(1.0f, 1.0f, 1.0f);
2622         glTexCoord2f(glTexCoord[0], glTexCoord[2]);
2623         glVertex3f(rect.x1,
2624                     rect.y1,
2625                     0.0);
2626
2627         glTexCoord2f(glTexCoord[0], glTexCoord[3]);
2628         glVertex3f(rect.x1, rect.y2, 0.0);
2629
2630         glTexCoord2f(glTexCoord[1], glTexCoord[3]);
2631         glVertex3f(rect.x2,
2632                     rect.y2,
2633                     0.0);
2634
2635         glTexCoord2f(glTexCoord[1], glTexCoord[2]);
2636         glVertex3f(rect.x2,
2637                     rect.y1,
2638                     0.0);
2639         glEnd();
2640         checkGLcall("glEnd");
2641
2642         /* Unbind the texture */
2643         glBindTexture(GL_TEXTURE_2D, 0);
2644         checkGLcall("glEnable glBindTexture");
2645
2646         if(This == (IWineD3DSurfaceImpl *) dstSwapchain->frontBuffer && oldDraw == GL_BACK) {
2647             glDrawBuffer(oldDraw);
2648         }
2649         /* Restore the color key parameters */
2650         Src->CKeyFlags = oldCKeyFlags;
2651         This->SrcBltCKey = oldBltCKey;
2652
2653         LEAVE_GL();
2654
2655         /* TODO: If the surface is locked often, perform the Blt in software on the memory instead */
2656         This->Flags |= SFLAG_GLDIRTY;
2657
2658         return WINED3D_OK;
2659     } else {
2660         /* Source-Less Blit to render target */
2661         if (Flags & DDBLT_COLORFILL) {
2662             /* This is easy to handle for the D3D Device... */
2663             DWORD color;
2664
2665             TRACE("Colorfill\n");
2666
2667             /* The color as given in the Blt function is in the format of the frame-buffer...
2668              * 'clear' expect it in ARGB format => we need to do some conversion :-)
2669              */
2670             if (This->resource.format == WINED3DFMT_P8) {
2671                 if (This->palette) {
2672                     color = ((0xFF000000) |
2673                             (This->palette->palents[DDBltFx->u5.dwFillColor].peRed << 16) |
2674                             (This->palette->palents[DDBltFx->u5.dwFillColor].peGreen << 8) |
2675                             (This->palette->palents[DDBltFx->u5.dwFillColor].peBlue));
2676                 } else {
2677                     color = 0xFF000000;
2678                 }
2679             }
2680             else if (This->resource.format == WINED3DFMT_R5G6B5) {
2681                 if (DDBltFx->u5.dwFillColor == 0xFFFF) {
2682                     color = 0xFFFFFFFF;
2683                 } else {
2684                     color = ((0xFF000000) |
2685                             ((DDBltFx->u5.dwFillColor & 0xF800) << 8) |
2686                             ((DDBltFx->u5.dwFillColor & 0x07E0) << 5) |
2687                             ((DDBltFx->u5.dwFillColor & 0x001F) << 3));
2688                 }
2689             }
2690             else if ((This->resource.format == WINED3DFMT_R8G8B8) ||
2691                     (This->resource.format == WINED3DFMT_X8R8G8B8) ) {
2692                 color = 0xFF000000 | DDBltFx->u5.dwFillColor;
2693             }
2694             else if (This->resource.format == WINED3DFMT_A8R8G8B8) {
2695                 color = DDBltFx->u5.dwFillColor;
2696             }
2697             else {
2698                 ERR("Wrong surface type for BLT override(Format doesn't match) !\n");
2699                 return WINED3DERR_INVALIDCALL;
2700             }
2701
2702             TRACE("Calling GetSwapChain with mydevice = %p\n", myDevice);
2703             if(dstSwapchain && dstSwapchain->backBuffer && This == (IWineD3DSurfaceImpl*) dstSwapchain->backBuffer[0]) {
2704                 glDrawBuffer(GL_BACK);
2705                 checkGLcall("glDrawBuffer(GL_BACK)");
2706             } else if (dstSwapchain && This == (IWineD3DSurfaceImpl*) dstSwapchain->frontBuffer) {
2707                 glDrawBuffer(GL_FRONT);
2708                 checkGLcall("glDrawBuffer(GL_FRONT)");
2709             } else if(This == (IWineD3DSurfaceImpl *) myDevice->render_targets[0]) {
2710                 glDrawBuffer(GL_BACK);
2711                 checkGLcall("glDrawBuffer(GL_BACK)");
2712             } else {
2713                 TRACE("Surface is higher back buffer, falling back to software\n");
2714                 return WINED3DERR_INVALIDCALL;
2715             }
2716
2717             TRACE("(%p) executing Render Target override, color = %x\n", This, color);
2718
2719             IWineD3DDevice_Clear( (IWineD3DDevice *) myDevice,
2720                                 1 /* Number of rectangles */,
2721                                 &rect,
2722                                 WINED3DCLEAR_TARGET,
2723                                 color,
2724                                 0.0 /* Z */,
2725                                 0 /* Stencil */);
2726
2727             /* Restore the original draw buffer */
2728             if(!dstSwapchain || (dstSwapchain->backBuffer && dstSwapchain->backBuffer[0])) {
2729                 glDrawBuffer(GL_BACK);
2730                 vcheckGLcall("glDrawBuffer");
2731             }
2732
2733             return WINED3D_OK;
2734         }
2735     }
2736
2737     /* Default: Fall back to the generic blt. Not an error, a TRACE is enought */
2738     TRACE("Didn't find any usable render target setup for hw blit, falling back to software\n");
2739     return WINED3DERR_INVALIDCALL;
2740 }
2741
2742 static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
2743     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2744     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2745     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
2746     TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2747     TRACE("(%p): Usage is %s\n", This, debug_d3dusage(This->resource.usage));
2748
2749     /* Accessing the depth stencil is supposed to fail between a BeginScene and EndScene pair */
2750     if(myDevice->inScene &&
2751        (iface == myDevice->stencilBufferTarget ||
2752        (SrcSurface && SrcSurface == myDevice->stencilBufferTarget))) {
2753         TRACE("Attempt to access the depth stencil surface in a BeginScene / EndScene pair, returning WINED3DERR_INVALIDCALL\n");
2754         return WINED3DERR_INVALIDCALL;
2755     }
2756
2757     /* Special cases for RenderTargets */
2758     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
2759         ( Src && (Src->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
2760         if(IWineD3DSurfaceImpl_BltOverride(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx) == WINED3D_OK) return WINED3D_OK;
2761     }
2762
2763     /* For the rest call the X11 surface implementation.
2764      * For RenderTargets this should be implemented OpenGL accelerated in BltOverride,
2765      * other Blts are rather rare
2766      */
2767     return IWineGDISurfaceImpl_Blt(iface, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2768 }
2769
2770 HRESULT WINAPI IWineD3DSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD Flags) {
2771     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2772     TRACE("(%p)->(%x)\n", This, Flags);
2773
2774     switch (Flags)
2775     {
2776     case DDGBS_CANBLT:
2777     case DDGBS_ISBLTDONE:
2778         return DD_OK;
2779
2780     default:
2781         return DDERR_INVALIDPARAMS;
2782     }
2783 }
2784
2785 HRESULT WINAPI IWineD3DSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD Flags) {
2786     /* XXX: DDERR_INVALIDSURFACETYPE */
2787
2788     TRACE("(%p)->(%08x)\n",iface,Flags);
2789     switch (Flags) {
2790     case DDGFS_CANFLIP:
2791     case DDGFS_ISFLIPDONE:
2792         return DD_OK;
2793
2794     default:
2795         return DDERR_INVALIDPARAMS;
2796     }
2797 }
2798
2799 HRESULT WINAPI IWineD3DSurfaceImpl_IsLost(IWineD3DSurface *iface) {
2800     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2801     TRACE("(%p)\n", This);
2802
2803     return This->Flags & SFLAG_LOST ? DDERR_SURFACELOST : WINED3D_OK;
2804 }
2805
2806 HRESULT WINAPI IWineD3DSurfaceImpl_Restore(IWineD3DSurface *iface) {
2807     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2808     TRACE("(%p)\n", This);
2809
2810     /* So far we don't lose anything :) */
2811     This->Flags &= ~SFLAG_LOST;
2812     return WINED3D_OK;
2813 }
2814
2815 HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty, IWineD3DSurface *Source, RECT *rsrc, DWORD trans) {
2816     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2817     IWineD3DSurfaceImpl *srcImpl = (IWineD3DSurfaceImpl *) Source;
2818     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
2819     TRACE("(%p)->(%d, %d, %p, %p, %08x\n", iface, dstx, dsty, Source, rsrc, trans);
2820
2821     if(myDevice->inScene &&
2822        (iface == myDevice->stencilBufferTarget ||
2823        (Source && Source == myDevice->stencilBufferTarget))) {
2824         TRACE("Attempt to access the depth stencil surface in a BeginScene / EndScene pair, returning WINED3DERR_INVALIDCALL\n");
2825         return WINED3DERR_INVALIDCALL;
2826     }
2827
2828     /* Special cases for RenderTargets */
2829     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
2830         ( srcImpl && (srcImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
2831
2832         RECT SrcRect, DstRect;
2833         DWORD Flags=0;
2834
2835         if(rsrc) {
2836             SrcRect.left = rsrc->left;
2837             SrcRect.top= rsrc->top;
2838             SrcRect.bottom = rsrc->bottom;
2839             SrcRect.right = rsrc->right;
2840         } else {
2841             SrcRect.left = 0;
2842             SrcRect.top = 0;
2843             SrcRect.right = srcImpl->currentDesc.Width;
2844             SrcRect.bottom = srcImpl->currentDesc.Height;
2845         }
2846
2847         DstRect.left = dstx;
2848         DstRect.top=dsty;
2849         DstRect.right = dstx + SrcRect.right - SrcRect.left;
2850         DstRect.bottom = dsty + SrcRect.bottom - SrcRect.top;
2851
2852         /* Convert BltFast flags into Btl ones because it is called from SurfaceImpl_Blt as well */
2853         if(trans & DDBLTFAST_SRCCOLORKEY)
2854             Flags |= DDBLT_KEYSRC;
2855         if(trans & DDBLTFAST_DESTCOLORKEY)
2856             Flags |= DDBLT_KEYDEST;
2857         if(trans & DDBLTFAST_WAIT)
2858             Flags |= DDBLT_WAIT;
2859         if(trans & DDBLTFAST_DONOTWAIT)
2860             Flags |= DDBLT_DONOTWAIT;
2861
2862         if(IWineD3DSurfaceImpl_BltOverride(This, &DstRect, Source, &SrcRect, Flags, NULL) == WINED3D_OK) return WINED3D_OK;
2863     }
2864
2865
2866     return IWineGDISurfaceImpl_BltFast(iface, dstx, dsty, Source, rsrc, trans);
2867 }
2868
2869 HRESULT WINAPI IWineD3DSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD3DPalette **Pal) {
2870     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2871     TRACE("(%p)->(%p)\n", This, Pal);
2872
2873     *Pal = (IWineD3DPalette *) This->palette;
2874     return DD_OK;
2875 }
2876
2877 HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) {
2878     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2879     RGBQUAD col[256];
2880     IWineD3DPaletteImpl *pal = This->palette;
2881     unsigned int n;
2882     TRACE("(%p)\n", This);
2883
2884     if(This->resource.format == WINED3DFMT_P8 ||
2885        This->resource.format == WINED3DFMT_A8P8)
2886     {
2887         TRACE("Dirtifying surface\n");
2888         This->Flags |= SFLAG_DIRTY;
2889     }
2890
2891     if(This->Flags & SFLAG_DIBSECTION) {
2892         TRACE("(%p): Updating the hdc's palette\n", This);
2893         for (n=0; n<256; n++) {
2894             if(pal) {
2895                 col[n].rgbRed   = pal->palents[n].peRed;
2896                 col[n].rgbGreen = pal->palents[n].peGreen;
2897                 col[n].rgbBlue  = pal->palents[n].peBlue;
2898             } else {
2899                 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2900                 /* Use the default device palette */
2901                 col[n].rgbRed   = device->palettes[device->currentPalette][n].peRed;
2902                 col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
2903                 col[n].rgbBlue  = device->palettes[device->currentPalette][n].peBlue;
2904             }
2905             col[n].rgbReserved = 0;
2906         }
2907         SetDIBColorTable(This->hDC, 0, 256, col);
2908     }
2909
2910     return WINED3D_OK;
2911 }
2912
2913 HRESULT WINAPI IWineD3DSurfaceImpl_SetPalette(IWineD3DSurface *iface, IWineD3DPalette *Pal) {
2914     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2915     IWineD3DPaletteImpl *PalImpl = (IWineD3DPaletteImpl *) Pal;
2916     TRACE("(%p)->(%p)\n", This, Pal);
2917
2918     if(This->palette != NULL) 
2919         if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
2920             This->palette->Flags &= ~DDPCAPS_PRIMARYSURFACE;
2921
2922     if(PalImpl != NULL) {
2923         if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
2924             /* Set the device's main palette if the palette
2925              * wasn't a primary palette before
2926              */
2927             if(!(PalImpl->Flags & DDPCAPS_PRIMARYSURFACE)) {
2928                 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2929                 unsigned int i;
2930
2931                 for(i=0; i < 256; i++) {
2932                     device->palettes[device->currentPalette][i] = PalImpl->palents[i];
2933                 }
2934             }
2935
2936             (PalImpl)->Flags |= DDPCAPS_PRIMARYSURFACE;
2937         }
2938     }
2939     This->palette = PalImpl;
2940
2941     return IWineD3DSurface_RealizePalette(iface);
2942 }
2943
2944 HRESULT WINAPI IWineD3DSurfaceImpl_SetColorKey(IWineD3DSurface *iface, DWORD Flags, DDCOLORKEY *CKey) {
2945     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2946     TRACE("(%p)->(%08x,%p)\n", This, Flags, CKey);
2947
2948     if ((Flags & DDCKEY_COLORSPACE) != 0) {
2949         FIXME(" colorkey value not supported (%08x) !\n", Flags);
2950         return DDERR_INVALIDPARAMS;
2951     }
2952
2953     /* Dirtify the surface, but only if a key was changed */
2954     if(CKey) {
2955         switch (Flags & ~DDCKEY_COLORSPACE) {
2956             case DDCKEY_DESTBLT:
2957                 This->DestBltCKey = *CKey;
2958                 This->CKeyFlags |= DDSD_CKDESTBLT;
2959                 break;
2960
2961             case DDCKEY_DESTOVERLAY:
2962                 This->DestOverlayCKey = *CKey;
2963                 This->CKeyFlags |= DDSD_CKDESTOVERLAY;
2964                 break;
2965
2966             case DDCKEY_SRCOVERLAY:
2967                 This->SrcOverlayCKey = *CKey;
2968                 This->CKeyFlags |= DDSD_CKSRCOVERLAY;
2969                 break;
2970
2971             case DDCKEY_SRCBLT:
2972                 This->SrcBltCKey = *CKey;
2973                 This->CKeyFlags |= DDSD_CKSRCBLT;
2974                 break;
2975         }
2976     }
2977     else {
2978         switch (Flags & ~DDCKEY_COLORSPACE) {
2979             case DDCKEY_DESTBLT:
2980                 This->CKeyFlags &= ~DDSD_CKDESTBLT;
2981                 break;
2982
2983             case DDCKEY_DESTOVERLAY:
2984                 This->CKeyFlags &= ~DDSD_CKDESTOVERLAY;
2985                 break;
2986
2987             case DDCKEY_SRCOVERLAY:
2988                 This->CKeyFlags &= ~DDSD_CKSRCOVERLAY;
2989                 break;
2990
2991             case DDCKEY_SRCBLT:
2992                 This->CKeyFlags &= ~DDSD_CKSRCBLT;
2993                 break;
2994         }
2995     }
2996
2997     return WINED3D_OK;
2998 }
2999
3000 static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) {
3001     /** Check against the maximum texture sizes supported by the video card **/
3002     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3003
3004     TRACE("%p\n", This);
3005     if ((This->pow2Width > GL_LIMITS(texture_size) || This->pow2Height > GL_LIMITS(texture_size)) && !(This->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))) {
3006         /* one of three options
3007         1: Do the same as we do with nonpow 2 and scale the texture, (any texture ops would require the texture to be scaled which is potentially slow)
3008         2: Set the texture to the maxium size (bad idea)
3009         3:    WARN and return WINED3DERR_NOTAVAILABLE;
3010         4: Create the surface, but allow it to be used only for DirectDraw Blts. Some apps(e.g. Swat 3) create textures with a Height of 16 and a Width > 3000 and blt 16x16 letter areas from them to the render target.
3011         */
3012         WARN("(%p) Creating an oversized surface\n", This);
3013         This->Flags |= SFLAG_OVERSIZE;
3014
3015         /* This will be initialized on the first blt */
3016         This->glRect.left = 0;
3017         This->glRect.top = 0;
3018         This->glRect.right = 0;
3019         This->glRect.bottom = 0;
3020     } else {
3021         /* No oversize, gl rect is the full texture size */
3022         This->Flags &= ~SFLAG_OVERSIZE;
3023         This->glRect.left = 0;
3024         This->glRect.top = 0;
3025         This->glRect.right = This->pow2Width;
3026         This->glRect.bottom = This->pow2Height;
3027     }
3028
3029     return WINED3D_OK;
3030 }
3031
3032 DWORD WINAPI IWineD3DSurfaceImpl_GetPitch(IWineD3DSurface *iface) {
3033     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3034     DWORD ret;
3035     TRACE("(%p)\n", This);
3036
3037     /* DXTn formats don't have exact pitches as they are to the new row of blocks,
3038          where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt2/3/4/5)
3039           ie pitch = (width/4) * bytes per block                                  */
3040     if (This->resource.format == WINED3DFMT_DXT1) /* DXT1 is 8 bytes per block */
3041         ret = ((This->currentDesc.Width + 3) >> 2) << 3;
3042     else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
3043              This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */
3044         ret = ((This->currentDesc.Width + 3) >> 2) << 4;
3045     else {
3046         ret = This->bytesPerPixel * This->currentDesc.Width;  /* Bytes / row */
3047         /* Surfaces are 32 bit aligned */
3048         ret = (ret + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
3049     }
3050     TRACE("(%p) Returning %d\n", This, ret);
3051     return ret;
3052 }
3053
3054 HRESULT WINAPI IWineD3DSurfaceImpl_SetOverlayPosition(IWineD3DSurface *iface, LONG X, LONG Y) {
3055     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3056
3057     FIXME("(%p)->(%d,%d) Stub!\n", This, X, Y);
3058
3059     if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3060     {
3061         TRACE("(%p): Not an overlay surface\n", This);
3062         return DDERR_NOTAOVERLAYSURFACE;
3063     }
3064
3065     return WINED3D_OK;
3066 }
3067
3068 HRESULT WINAPI IWineD3DSurfaceImpl_GetOverlayPosition(IWineD3DSurface *iface, LONG *X, LONG *Y) {
3069     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3070
3071     FIXME("(%p)->(%p,%p) Stub!\n", This, X, Y);
3072
3073     if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3074     {
3075         TRACE("(%p): Not an overlay surface\n", This);
3076         return DDERR_NOTAOVERLAYSURFACE;
3077     }
3078
3079     return WINED3D_OK;
3080 }
3081
3082 HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface *iface, DWORD Flags, IWineD3DSurface *Ref) {
3083     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3084     IWineD3DSurfaceImpl *RefImpl = (IWineD3DSurfaceImpl *) Ref;
3085
3086     FIXME("(%p)->(%08x,%p) Stub!\n", This, Flags, RefImpl);
3087
3088     if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3089     {
3090         TRACE("(%p): Not an overlay surface\n", This);
3091         return DDERR_NOTAOVERLAYSURFACE;
3092     }
3093
3094     return WINED3D_OK;
3095 }
3096
3097 HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, RECT *SrcRect, IWineD3DSurface *DstSurface, RECT *DstRect, DWORD Flags, WINEDDOVERLAYFX *FX) {
3098     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3099     IWineD3DSurfaceImpl *Dst = (IWineD3DSurfaceImpl *) DstSurface;
3100     FIXME("(%p)->(%p, %p, %p, %08x, %p)\n", This, SrcRect, Dst, DstRect, Flags, FX);
3101
3102     if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3103     {
3104         TRACE("(%p): Not an overlay surface\n", This);
3105         return DDERR_NOTAOVERLAYSURFACE;
3106     }
3107
3108     return WINED3D_OK;
3109 }
3110
3111 const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
3112 {
3113     /* IUnknown */
3114     IWineD3DSurfaceImpl_QueryInterface,
3115     IWineD3DSurfaceImpl_AddRef,
3116     IWineD3DSurfaceImpl_Release,
3117     /* IWineD3DResource */
3118     IWineD3DSurfaceImpl_GetParent,
3119     IWineD3DSurfaceImpl_GetDevice,
3120     IWineD3DSurfaceImpl_SetPrivateData,
3121     IWineD3DSurfaceImpl_GetPrivateData,
3122     IWineD3DSurfaceImpl_FreePrivateData,
3123     IWineD3DSurfaceImpl_SetPriority,
3124     IWineD3DSurfaceImpl_GetPriority,
3125     IWineD3DSurfaceImpl_PreLoad,
3126     IWineD3DSurfaceImpl_GetType,
3127     /* IWineD3DSurface */
3128     IWineD3DSurfaceImpl_GetContainer,
3129     IWineD3DSurfaceImpl_GetDesc,
3130     IWineD3DSurfaceImpl_LockRect,
3131     IWineD3DSurfaceImpl_UnlockRect,
3132     IWineD3DSurfaceImpl_GetDC,
3133     IWineD3DSurfaceImpl_ReleaseDC,
3134     IWineD3DSurfaceImpl_Flip,
3135     IWineD3DSurfaceImpl_Blt,
3136     IWineD3DSurfaceImpl_GetBltStatus,
3137     IWineD3DSurfaceImpl_GetFlipStatus,
3138     IWineD3DSurfaceImpl_IsLost,
3139     IWineD3DSurfaceImpl_Restore,
3140     IWineD3DSurfaceImpl_BltFast,
3141     IWineD3DSurfaceImpl_GetPalette,
3142     IWineD3DSurfaceImpl_SetPalette,
3143     IWineD3DSurfaceImpl_RealizePalette,
3144     IWineD3DSurfaceImpl_SetColorKey,
3145     IWineD3DSurfaceImpl_GetPitch,
3146     IWineD3DSurfaceImpl_SetMem,
3147     IWineD3DSurfaceImpl_SetOverlayPosition,
3148     IWineD3DSurfaceImpl_GetOverlayPosition,
3149     IWineD3DSurfaceImpl_UpdateOverlayZOrder,
3150     IWineD3DSurfaceImpl_UpdateOverlay,
3151     /* Internal use: */
3152     IWineD3DSurfaceImpl_CleanDirtyRect,
3153     IWineD3DSurfaceImpl_AddDirtyRect,
3154     IWineD3DSurfaceImpl_LoadTexture,
3155     IWineD3DSurfaceImpl_SaveSnapshot,
3156     IWineD3DSurfaceImpl_SetContainer,
3157     IWineD3DSurfaceImpl_SetPBufferState,
3158     IWineD3DSurfaceImpl_SetGlTextureDesc,
3159     IWineD3DSurfaceImpl_GetGlDesc,
3160     IWineD3DSurfaceImpl_GetData,
3161     IWineD3DSurfaceImpl_SetFormat,
3162     IWineD3DSurfaceImpl_PrivateSetup
3163 };