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