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