quartz: Use proper alloc/free functions for COM objects.
[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 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_NV_texture_shader and GL_ATI_envmap_bumpmap provide suitable formats.
1459              * use one of them instead of converting
1460              * Remember to adjust the texbem instruction in the shader
1461              */
1462             *convert = CONVERT_V8U8;
1463             *format = GL_BGR;
1464             *internal = GL_RGB8;
1465             *type = GL_BYTE;
1466             *target_bpp = 3;
1467             break;
1468
1469         default:
1470             break;
1471     }
1472
1473     return WINED3D_OK;
1474 }
1475
1476 HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *surf) {
1477     BYTE *source, *dest;
1478     TRACE("(%p)->(%p),(%d,%d,%d,%d,%p)\n", src, dst, pitch, height, outpitch, convert, surf);
1479
1480     switch (convert) {
1481         case NO_CONVERSION:
1482         {
1483             memcpy(dst, src, pitch * height);
1484             break;
1485         }
1486         case CONVERT_PALETTED:
1487         case CONVERT_PALETTED_CK:
1488         {
1489             IWineD3DPaletteImpl* pal = surf->palette;
1490             BYTE table[256][4];
1491             unsigned int i;
1492             unsigned int x, y;
1493
1494             if( pal == NULL) {
1495                 /* TODO: If we are a sublevel, try to get the palette from level 0 */
1496             }
1497
1498             if (pal == NULL) {
1499                 /* Still no palette? Use the device's palette */
1500                 /* Get the surface's palette */
1501                 for (i = 0; i < 256; i++) {
1502                     IWineD3DDeviceImpl *device = surf->resource.wineD3DDevice;
1503
1504                     table[i][0] = device->palettes[device->currentPalette][i].peRed;
1505                     table[i][1] = device->palettes[device->currentPalette][i].peGreen;
1506                     table[i][2] = device->palettes[device->currentPalette][i].peBlue;
1507                     if ((convert == CONVERT_PALETTED_CK) &&
1508                         (i >= surf->SrcBltCKey.dwColorSpaceLowValue) &&
1509                         (i <= surf->SrcBltCKey.dwColorSpaceHighValue)) {
1510                         /* We should maybe here put a more 'neutral' color than the standard bright purple
1511                           one often used by application to prevent the nice purple borders when bi-linear
1512                           filtering is on */
1513                         table[i][3] = 0x00;
1514                     } else {
1515                         table[i][3] = 0xFF;
1516                     }
1517                 }
1518             } else {
1519                 TRACE("Using surface palette %p\n", pal);
1520                 /* Get the surface's palette */
1521                 for (i = 0; i < 256; i++) {
1522                     table[i][0] = pal->palents[i].peRed;
1523                     table[i][1] = pal->palents[i].peGreen;
1524                     table[i][2] = pal->palents[i].peBlue;
1525                     if ((convert == CONVERT_PALETTED_CK) &&
1526                         (i >= surf->SrcBltCKey.dwColorSpaceLowValue) &&
1527                         (i <= surf->SrcBltCKey.dwColorSpaceHighValue)) {
1528                         /* We should maybe here put a more 'neutral' color than the standard bright purple
1529                           one often used by application to prevent the nice purple borders when bi-linear
1530                           filtering is on */
1531                         table[i][3] = 0x00;
1532                     } else {
1533                         table[i][3] = 0xFF;
1534                     }
1535                 }
1536             }
1537
1538             for (y = 0; y < height; y++)
1539             {
1540                 source = src + pitch * y;
1541                 dest = dst + outpitch * y;
1542                 /* This is an 1 bpp format, using the width here is fine */
1543                 for (x = 0; x < width; x++) {
1544                     BYTE color = *source++;
1545                     *dest++ = table[color][0];
1546                     *dest++ = table[color][1];
1547                     *dest++ = table[color][2];
1548                     *dest++ = table[color][3];
1549                 }
1550             }
1551         }
1552         break;
1553
1554         case CONVERT_CK_565:
1555         {
1556             /* Converting the 565 format in 5551 packed to emulate color-keying.
1557
1558               Note : in all these conversion, it would be best to average the averaging
1559                       pixels to get the color of the pixel that will be color-keyed to
1560                       prevent 'color bleeding'. This will be done later on if ever it is
1561                       too visible.
1562
1563               Note2: Nvidia documents say that their driver does not support alpha + color keying
1564                      on the same surface and disables color keying in such a case
1565             */
1566             unsigned int x, y;
1567             WORD *Source;
1568             WORD *Dest;
1569
1570             TRACE("Color keyed 565\n");
1571
1572             for (y = 0; y < height; y++) {
1573                 Source = (WORD *) (src + y * pitch);
1574                 Dest = (WORD *) (dst + y * outpitch);
1575                 for (x = 0; x < width; x++ ) {
1576                     WORD color = *Source++;
1577                     *Dest = ((color & 0xFFC0) | ((color & 0x1F) << 1));
1578                     if ((color < surf->SrcBltCKey.dwColorSpaceLowValue) ||
1579                         (color > surf->SrcBltCKey.dwColorSpaceHighValue)) {
1580                         *Dest |= 0x0001;
1581                     }
1582                     Dest++;
1583                 }
1584             }
1585         }
1586         break;
1587
1588         case CONVERT_V8U8:
1589         {
1590             unsigned int x, y;
1591             short *Source;
1592             unsigned char *Dest;
1593             for(y = 0; y < height; y++) {
1594                 Source = (short *) (src + y * pitch);
1595                 Dest = (unsigned char *) (dst + y * outpitch);
1596                 for (x = 0; x < width; x++ ) {
1597                     long color = (*Source++);
1598                     /* B */ Dest[0] = 0xff;
1599                     /* G */ Dest[1] = (color >> 8) + 128; /* V */
1600                     /* R */ Dest[2] = (color) + 128;      /* U */
1601                     Dest += 3;
1602                 }
1603             }
1604             break;
1605         }
1606
1607         default:
1608             ERR("Unsupported conversation type %d\n", convert);
1609     }
1610     return WINED3D_OK;
1611 }
1612
1613 /* This function is used in case of 8bit paletted textures to upload the palette.
1614    For now it only supports GL_EXT_paletted_texture extension but support for other
1615    extensions like ARB_fragment_program and ATI_fragment_shaders will be added as well.
1616 */
1617 void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES convert) {
1618     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1619     IWineD3DPaletteImpl* pal = This->palette;
1620     BYTE table[256][4];
1621     int i;
1622
1623     if (pal == NULL) {
1624         /* Still no palette? Use the device's palette */
1625         /* Get the surface's palette */
1626         for (i = 0; i < 256; i++) {
1627             IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1628
1629             table[i][0] = device->palettes[device->currentPalette][i].peRed;
1630             table[i][1] = device->palettes[device->currentPalette][i].peGreen;
1631             table[i][2] = device->palettes[device->currentPalette][i].peBlue;
1632             if ((convert == CONVERT_PALETTED_CK) &&
1633                 (i >= This->SrcBltCKey.dwColorSpaceLowValue) &&
1634                 (i <= This->SrcBltCKey.dwColorSpaceHighValue)) {
1635                 /* We should maybe here put a more 'neutral' color than the standard bright purple
1636                    one often used by application to prevent the nice purple borders when bi-linear
1637                    filtering is on */
1638                 table[i][3] = 0x00;
1639             } else {
1640                 table[i][3] = 0xFF;
1641             }
1642         }
1643     } else {
1644         TRACE("Using surface palette %p\n", pal);
1645         /* Get the surface's palette */
1646         for (i = 0; i < 256; i++) {
1647             table[i][0] = pal->palents[i].peRed;
1648             table[i][1] = pal->palents[i].peGreen;
1649             table[i][2] = pal->palents[i].peBlue;
1650             if ((convert == CONVERT_PALETTED_CK) &&
1651                 (i >= This->SrcBltCKey.dwColorSpaceLowValue) &&
1652                 (i <= This->SrcBltCKey.dwColorSpaceHighValue)) {
1653                 /* We should maybe here put a more 'neutral' color than the standard bright purple
1654                    one often used by application to prevent the nice purple borders when bi-linear
1655                    filtering is on */
1656                 table[i][3] = 0x00;
1657             } else {
1658                 table[i][3] = 0xFF;
1659             }
1660         }
1661     }
1662     GL_EXTCALL(glColorTableEXT(GL_TEXTURE_2D,GL_RGBA,256,GL_RGBA,GL_UNSIGNED_BYTE, table));
1663 }
1664
1665 static BOOL palette9_changed(IWineD3DSurfaceImpl *This) {
1666     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1667
1668     if(This->palette || (This->resource.format != WINED3DFMT_P8 && This->resource.format != WINED3DFMT_A8P8)) {
1669         /* If a ddraw-style palette is attached assume no d3d9 palette change.
1670          * Also the palette isn't interesting if the surface format isn't P8 or A8P8
1671          */
1672         return FALSE;
1673     }
1674
1675     if(This->palette9) {
1676         if(memcmp(This->palette9, &device->palettes[device->currentPalette], sizeof(PALETTEENTRY) * 256) == 0) {
1677             return FALSE;
1678         }
1679     } else {
1680         This->palette9 = (PALETTEENTRY *) HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY) * 256);
1681     }
1682     memcpy(This->palette9, &device->palettes[device->currentPalette], sizeof(PALETTEENTRY) * 256);
1683     return TRUE;
1684 }
1685
1686 static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface) {
1687     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1688     GLenum format, internal, type;
1689     CONVERT_TYPES convert;
1690     int bpp;
1691     int width, pitch, outpitch;
1692     BYTE *mem;
1693
1694     if (!(This->Flags & SFLAG_INTEXTURE)) {
1695         TRACE("Reloading because surface is dirty\n");
1696     } else if(/* Reload: gl texture has ck, now no ckey is set OR */
1697               ((This->Flags & SFLAG_GLCKEY) && (!(This->CKeyFlags & DDSD_CKSRCBLT))) ||
1698               /* Reload: vice versa  OR */
1699               ((!(This->Flags & SFLAG_GLCKEY)) && (This->CKeyFlags & DDSD_CKSRCBLT)) ||
1700               /* Also reload: Color key is active AND the color key has changed */
1701               ((This->CKeyFlags & DDSD_CKSRCBLT) && (
1702                 (This->glCKey.dwColorSpaceLowValue != This->SrcBltCKey.dwColorSpaceLowValue) ||
1703                 (This->glCKey.dwColorSpaceHighValue != This->SrcBltCKey.dwColorSpaceHighValue)))) {
1704         TRACE("Reloading because of color keying\n");
1705     } else if(palette9_changed(This)) {
1706         TRACE("Reloading surface because the d3d8/9 palette was changed\n");
1707     } else {
1708         TRACE("surface is already in texture\n");
1709         return WINED3D_OK;
1710     }
1711
1712     This->Flags |= SFLAG_INTEXTURE;
1713
1714     /* Resources are placed in system RAM and do not need to be recreated when a device is lost.
1715     *  These resources are not bound by device size or format restrictions. Because of this,
1716     *  these resources cannot be accessed by the Direct3D device nor set as textures or render targets.
1717     *  However, these resources can always be created, locked, and copied.
1718     */
1719     if (This->resource.pool == WINED3DPOOL_SCRATCH && !(This->Flags & SFLAG_FORCELOAD) )
1720     {
1721         FIXME("(%p) Operation not supported for scratch textures\n",This);
1722         return WINED3DERR_INVALIDCALL;
1723     }
1724
1725     if (This->Flags & SFLAG_INDRAWABLE) {
1726         if (This->glDescription.level != 0)
1727             FIXME("Surface in texture is only supported for level 0\n");
1728         else if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8 ||
1729                  This->resource.format == WINED3DFMT_DXT1 || This->resource.format == WINED3DFMT_DXT2 ||
1730                  This->resource.format == WINED3DFMT_DXT3 || This->resource.format == WINED3DFMT_DXT4 ||
1731                  This->resource.format == WINED3DFMT_DXT5)
1732             FIXME("Format %d not supported\n", This->resource.format);
1733         else {
1734             GLint prevRead;
1735
1736             ENTER_GL();
1737             glGetIntegerv(GL_READ_BUFFER, &prevRead);
1738             vcheckGLcall("glGetIntegerv");
1739             glReadBuffer(This->resource.wineD3DDevice->offscreenBuffer);
1740             vcheckGLcall("glReadBuffer");
1741
1742             glCopyTexImage2D(This->glDescription.target,
1743                              This->glDescription.level,
1744                              This->glDescription.glFormatInternal,
1745                              0,
1746                              0,
1747                              This->currentDesc.Width,
1748                              This->currentDesc.Height,
1749                              0);
1750
1751             checkGLcall("glCopyTexImage2D");
1752             glReadBuffer(prevRead);
1753             vcheckGLcall("glReadBuffer");
1754
1755             LEAVE_GL();
1756
1757             TRACE("Updated target %d\n", This->glDescription.target);
1758         }
1759         return WINED3D_OK;
1760     }
1761     /* Otherwise: System memory copy must be most up to date */
1762
1763     if(This->CKeyFlags & DDSD_CKSRCBLT) {
1764         This->Flags |= SFLAG_GLCKEY;
1765         This->glCKey = This->SrcBltCKey;
1766     }
1767     else This->Flags &= ~SFLAG_GLCKEY;
1768
1769     d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp);
1770
1771     /* The width is in 'length' not in bytes */
1772     width = This->currentDesc.Width;
1773     pitch = IWineD3DSurface_GetPitch(iface);
1774
1775     if((convert != NO_CONVERSION) && This->resource.allocatedMemory) {
1776         int height = This->currentDesc.Height;
1777
1778         /* Stick to the alignment for the converted surface too, makes it easier to load the surface */
1779         outpitch = width * bpp;
1780         outpitch = (outpitch + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
1781
1782         mem = HeapAlloc(GetProcessHeap(), 0, outpitch * height);
1783         if(!mem) {
1784             ERR("Out of memory %d, %d!\n", outpitch, height);
1785             return WINED3DERR_OUTOFVIDEOMEMORY;
1786         }
1787         d3dfmt_convert_surface(This->resource.allocatedMemory, mem, pitch, width, height, outpitch, convert, This);
1788
1789         This->Flags |= SFLAG_CONVERTED;
1790     } else if (This->resource.format == WINED3DFMT_P8 && GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
1791         d3dfmt_p8_upload_palette(iface, convert);
1792         This->Flags &= ~SFLAG_CONVERTED;
1793         mem = This->resource.allocatedMemory;
1794     } else {
1795         This->Flags &= ~SFLAG_CONVERTED;
1796         mem = This->resource.allocatedMemory;
1797     }
1798
1799     /* Make sure the correct pitch is used */
1800     glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
1801
1802     if ((This->Flags & SFLAG_NONPOW2) && !(This->Flags & SFLAG_OVERSIZE)) {
1803         TRACE("non power of two support\n");
1804         surface_allocate_surface(This, internal, This->pow2Width, This->pow2Height, format, type);
1805         if (mem) {
1806             surface_upload_data(This, This->currentDesc.Width, This->currentDesc.Height, format, type, mem);
1807         }
1808     } else {
1809         surface_allocate_surface(This, internal, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type);
1810         if (mem) {
1811             surface_upload_data(This, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type, mem);
1812         }
1813     }
1814
1815     /* Restore the default pitch */
1816     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1817
1818     if (mem != This->resource.allocatedMemory)
1819         HeapFree(GetProcessHeap(), 0, mem);
1820
1821 #if 0
1822     {
1823         static unsigned int gen = 0;
1824         char buffer[4096];
1825         ++gen;
1826         if ((gen % 10) == 0) {
1827             snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, This->glDescription.target, This->glDescription.level, gen);
1828             IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer);
1829         }
1830         /*
1831          * debugging crash code
1832          if (gen == 250) {
1833          void** test = NULL;
1834          *test = 0;
1835          }
1836          */
1837     }
1838 #endif
1839
1840     if (!(This->Flags & SFLAG_DONOTFREE)) {
1841         HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
1842         This->resource.allocatedMemory = NULL;
1843         This->Flags &= ~SFLAG_INSYSMEM;
1844     }
1845
1846     return WINED3D_OK;
1847 }
1848
1849 #include <errno.h>
1850 #include <stdio.h>
1851 HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename) {
1852     FILE* f = NULL;
1853     UINT i, y;
1854     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1855     char *allocatedMemory;
1856     char *textureRow;
1857     IWineD3DSwapChain *swapChain = NULL;
1858     int width, height;
1859     GLuint tmpTexture = 0;
1860     DWORD color;
1861     /*FIXME:
1862     Textures my not be stored in ->allocatedgMemory and a GlTexture
1863     so we should lock the surface before saving a snapshot, or at least check that
1864     */
1865     /* TODO: Compressed texture images can be obtained from the GL in uncompressed form
1866     by calling GetTexImage and in compressed form by calling
1867     GetCompressedTexImageARB.  Queried compressed images can be saved and
1868     later reused by calling CompressedTexImage[123]DARB.  Pre-compressed
1869     texture images do not need to be processed by the GL and should
1870     significantly improve texture loading performance relative to uncompressed
1871     images. */
1872
1873 /* Setup the width and height to be the internal texture width and height. */
1874     width  = This->pow2Width;
1875     height = This->pow2Height;
1876 /* check to see if were a 'virtual' texture e.g. were not a pbuffer of texture were a back buffer*/
1877     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapChain);
1878
1879     if (This->Flags & SFLAG_INDRAWABLE && !(This->Flags & SFLAG_INTEXTURE)) {
1880         /* if were not a real texture then read the back buffer into a real texture */
1881         /* we don't want to interfere with the back buffer so read the data into a temporary
1882          * texture and then save the data out of the temporary texture
1883          */
1884         GLint prevRead;
1885         ENTER_GL();
1886         TRACE("(%p) Reading render target into texture\n", This);
1887         glEnable(GL_TEXTURE_2D);
1888
1889         glGenTextures(1, &tmpTexture);
1890         glBindTexture(GL_TEXTURE_2D, tmpTexture);
1891
1892         glTexImage2D(GL_TEXTURE_2D,
1893                         0,
1894                         GL_RGBA,
1895                         width,
1896                         height,
1897                         0/*border*/,
1898                         GL_RGBA,
1899                         GL_UNSIGNED_INT_8_8_8_8_REV,
1900                         NULL);
1901
1902         glGetIntegerv(GL_READ_BUFFER, &prevRead);
1903         vcheckGLcall("glGetIntegerv");
1904         glReadBuffer(swapChain ? GL_BACK : This->resource.wineD3DDevice->offscreenBuffer);
1905         vcheckGLcall("glReadBuffer");
1906         glCopyTexImage2D(GL_TEXTURE_2D,
1907                             0,
1908                             GL_RGBA,
1909                             0,
1910                             0,
1911                             width,
1912                             height,
1913                             0);
1914
1915         checkGLcall("glCopyTexImage2D");
1916         glReadBuffer(prevRead);
1917         LEAVE_GL();
1918
1919     } else { /* bind the real texture, and make sure it up to date */
1920         IWineD3DSurface_PreLoad(iface);
1921     }
1922     allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width  * height * 4);
1923     ENTER_GL();
1924     FIXME("Saving texture level %d width %d height %d\n", This->glDescription.level, width, height);
1925     glGetTexImage(GL_TEXTURE_2D,
1926                 This->glDescription.level,
1927                 GL_RGBA,
1928                 GL_UNSIGNED_INT_8_8_8_8_REV,
1929                 allocatedMemory);
1930     checkGLcall("glTexImage2D");
1931     if (tmpTexture) {
1932         glBindTexture(GL_TEXTURE_2D, 0);
1933         glDeleteTextures(1, &tmpTexture);
1934     }
1935     LEAVE_GL();
1936
1937     f = fopen(filename, "w+");
1938     if (NULL == f) {
1939         ERR("opening of %s failed with: %s\n", filename, strerror(errno));
1940         return WINED3DERR_INVALIDCALL;
1941     }
1942 /* Save the dat out to a TGA file because 1: it's an easy raw format, 2: it supports an alpha chanel*/
1943     TRACE("(%p) opened %s with format %s\n", This, filename, debug_d3dformat(This->resource.format));
1944 /* TGA header */
1945     fputc(0,f);
1946     fputc(0,f);
1947     fputc(2,f);
1948     fputc(0,f);
1949     fputc(0,f);
1950     fputc(0,f);
1951     fputc(0,f);
1952     fputc(0,f);
1953     fputc(0,f);
1954     fputc(0,f);
1955     fputc(0,f);
1956     fputc(0,f);
1957 /* short width*/
1958     fwrite(&width,2,1,f);
1959 /* short height */
1960     fwrite(&height,2,1,f);
1961 /* format rgba */
1962     fputc(0x20,f);
1963     fputc(0x28,f);
1964 /* raw data */
1965     /* 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*/
1966     if(swapChain)
1967         textureRow = allocatedMemory + (width * (height - 1) *4);
1968     else
1969         textureRow = allocatedMemory;
1970     for (y = 0 ; y < height; y++) {
1971         for (i = 0; i < width;  i++) {
1972             color = *((DWORD*)textureRow);
1973             fputc((color >> 16) & 0xFF, f); /* B */
1974             fputc((color >>  8) & 0xFF, f); /* G */
1975             fputc((color >>  0) & 0xFF, f); /* R */
1976             fputc((color >> 24) & 0xFF, f); /* A */
1977             textureRow += 4;
1978         }
1979         /* take two rows of the pointer to the texture memory */
1980         if(swapChain)
1981             (textureRow-= width << 3);
1982
1983     }
1984     TRACE("Closing file\n");
1985     fclose(f);
1986
1987     if(swapChain) {
1988         IWineD3DSwapChain_Release(swapChain);
1989     }
1990     HeapFree(GetProcessHeap(), 0, allocatedMemory);
1991     return WINED3D_OK;
1992 }
1993
1994 /**
1995  *   Slightly inefficient way to handle multiple dirty rects but it works :)
1996  */
1997 extern HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) {
1998     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1999     IWineD3DBaseTexture *baseTexture = NULL;
2000     This->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INDRAWABLE);
2001     if (NULL != pDirtyRect) {
2002         This->dirtyRect.left   = min(This->dirtyRect.left,   pDirtyRect->left);
2003         This->dirtyRect.top    = min(This->dirtyRect.top,    pDirtyRect->top);
2004         This->dirtyRect.right  = max(This->dirtyRect.right,  pDirtyRect->right);
2005         This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
2006     } else {
2007         This->dirtyRect.left   = 0;
2008         This->dirtyRect.top    = 0;
2009         This->dirtyRect.right  = This->currentDesc.Width;
2010         This->dirtyRect.bottom = This->currentDesc.Height;
2011     }
2012     TRACE("(%p) : Dirty: yes, Rect:(%d,%d,%d,%d)\n", This, This->dirtyRect.left,
2013           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
2014     /* if the container is a basetexture then mark it dirty. */
2015     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
2016         TRACE("Passing to conatiner\n");
2017         IWineD3DBaseTexture_SetDirty(baseTexture, TRUE);
2018         IWineD3DBaseTexture_Release(baseTexture);
2019     }
2020     return WINED3D_OK;
2021 }
2022
2023 HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) {
2024     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2025
2026     TRACE("This %p, container %p\n", This, container);
2027
2028     /* We can't keep a reference to the container, since the container already keeps a reference to us. */
2029
2030     TRACE("Setting container to %p from %p\n", container, This->container);
2031     This->container = container;
2032
2033     return WINED3D_OK;
2034 }
2035
2036 HRESULT WINAPI IWineD3DSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
2037     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2038     const PixelFormatDesc *formatEntry = getFormatDescEntry(format);
2039
2040     if (This->resource.format != WINED3DFMT_UNKNOWN) {
2041         FIXME("(%p) : The foramt of the surface must be WINED3DFORMAT_UNKNOWN\n", This);
2042         return WINED3DERR_INVALIDCALL;
2043     }
2044
2045     TRACE("(%p) : Setting texture foramt to (%d,%s)\n", This, format, debug_d3dformat(format));
2046     if (format == WINED3DFMT_UNKNOWN) {
2047         This->resource.size = 0;
2048     } else if (format == WINED3DFMT_DXT1) {
2049         /* DXT1 is half byte per pixel */
2050         This->resource.size = ((max(This->pow2Width, 4) * formatEntry->bpp) * max(This->pow2Height, 4)) >> 1;
2051
2052     } else if (format == WINED3DFMT_DXT2 || format == WINED3DFMT_DXT3 ||
2053                format == WINED3DFMT_DXT4 || format == WINED3DFMT_DXT5) {
2054         This->resource.size = ((max(This->pow2Width, 4) * formatEntry->bpp) * max(This->pow2Height, 4));
2055     } else {
2056         This->resource.size = ((This->pow2Width * formatEntry->bpp) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
2057         This->resource.size *= This->pow2Height;
2058     }
2059
2060
2061     /* Setup some glformat defaults */
2062     This->glDescription.glFormat         = formatEntry->glFormat;
2063     This->glDescription.glFormatInternal = formatEntry->glInternal;
2064     This->glDescription.glType           = formatEntry->glType;
2065
2066     if (format != WINED3DFMT_UNKNOWN) {
2067         This->bytesPerPixel = formatEntry->bpp;
2068     } else {
2069         This->bytesPerPixel = 0;
2070     }
2071
2072     This->Flags |= (WINED3DFMT_D16_LOCKABLE == format) ? SFLAG_LOCKABLE : 0;
2073
2074     This->resource.format = format;
2075
2076     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);
2077
2078     return WINED3D_OK;
2079 }
2080
2081 HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) {
2082     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2083
2084     /* Render targets depend on their hdc, and we can't create a hdc on a user pointer */
2085     if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
2086         ERR("Not supported on render targets\n");
2087         return WINED3DERR_INVALIDCALL;
2088     }
2089
2090     if(This->Flags & (SFLAG_LOCKED | SFLAG_DCINUSE)) {
2091         WARN("Surface is locked or the HDC is in use\n");
2092         return WINED3DERR_INVALIDCALL;
2093     }
2094
2095     if(Mem && Mem != This->resource.allocatedMemory) {
2096
2097         /* Do I have to copy the old surface content? */
2098         if(This->Flags & SFLAG_DIBSECTION) {
2099                 /* Release the DC. No need to hold the critical section for the update
2100                  * Thread because this thread runs only on front buffers, but this method
2101                  * fails for render targets in the check above.
2102                  */
2103                 SelectObject(This->hDC, This->dib.holdbitmap);
2104                 DeleteDC(This->hDC);
2105                 /* Release the DIB section */
2106                 DeleteObject(This->dib.DIBsection);
2107                 This->dib.bitmap_data = NULL;
2108                 This->resource.allocatedMemory = NULL;
2109                 This->hDC = NULL;
2110                 This->Flags &= ~SFLAG_DIBSECTION;
2111         } else if(!(This->Flags & SFLAG_USERPTR)) {
2112             HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
2113         }
2114         This->resource.allocatedMemory = Mem;
2115         This->Flags |= SFLAG_USERPTR;
2116     } else if(This->Flags & SFLAG_USERPTR) {
2117         /* Lockrect and GetDC will re-create the dib section and allocated memory */
2118         This->resource.allocatedMemory = NULL;
2119         This->Flags &= ~SFLAG_USERPTR;
2120     }
2121     return WINED3D_OK;
2122 }
2123
2124 static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DSurface *override, DWORD Flags) {
2125     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2126     IWineD3DDevice *D3D = (IWineD3DDevice *) This->resource.wineD3DDevice;
2127     TRACE("(%p)->(%p,%x)\n", This, override, Flags);
2128
2129     /* Flipping is only supported on RenderTargets */
2130     if( !(This->resource.usage & WINED3DUSAGE_RENDERTARGET) ) return DDERR_NOTFLIPPABLE;
2131
2132     if(override) {
2133         /* DDraw sets this for the X11 surfaces, so don't confuse the user 
2134          * FIXME("(%p) Target override is not supported by now\n", This);
2135          * Additionally, it isn't really possible to support triple-buffering
2136          * properly on opengl at all
2137          */
2138     }
2139
2140     /* Flipping a OpenGL surface -> Use WineD3DDevice::Present */
2141     return IWineD3DDevice_Present(D3D, NULL, NULL, 0, NULL);
2142 }
2143
2144 /* Does a direct frame buffer -> texture copy. Stretching is done
2145  * with single pixel copy calls
2146  */
2147 static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3DSurface *SrcSurface, IWineD3DSwapChainImpl *swapchain, WINED3DRECT *srect, WINED3DRECT *drect, BOOL upsidedown) {
2148     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
2149     float xrel, yrel;
2150     UINT row;
2151     BOOL warned = FALSE; /* deliberately not static */
2152     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2153
2154     ENTER_GL();
2155
2156     ActivateContext(myDevice, SrcSurface, CTXUSAGE_BLIT);
2157
2158     /* Bind the target texture */
2159     glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
2160     checkGLcall("glBindTexture");
2161     if(!swapchain) {
2162         glReadBuffer(myDevice->offscreenBuffer);
2163     } else if(swapchain->backBuffer && SrcSurface == swapchain->backBuffer[0]) {
2164         glReadBuffer(GL_BACK);
2165     } else {
2166         glReadBuffer(GL_FRONT);
2167     }
2168     checkGLcall("glReadBuffer");
2169
2170     xrel = (float) (srect->x2 - srect->x1) / (float) (drect->x2 - drect->x1);
2171     yrel = (float) (srect->y2 - srect->y1) / (float) (drect->y2 - drect->y1);
2172
2173     if( (xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) {
2174         FIXME("Doing a pixel by pixel copy from the framebuffer to a texture, expect major performance issues\n");
2175     }
2176
2177     if(upsidedown &&
2178        !((xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) &&
2179        !((yrel - 1.0 < -eps) || (yrel - 1.0 > eps))) {
2180         /* Upside down copy without stretching is nice, one glCopyTexSubImage call will do */
2181
2182         glCopyTexSubImage2D(This->glDescription.target,
2183                             This->glDescription.level,
2184                             drect->x1, drect->y1, /* xoffset, yoffset */
2185                             srect->x1, Src->currentDesc.Height - srect->y2,
2186                             drect->x2 - drect->x1, drect->y2 - drect->y1);
2187     } else {
2188         UINT yoffset = Src->currentDesc.Height - srect->y1 + drect->y1 - 1;
2189         /* I have to process this row by row to swap the image,
2190          * otherwise it would be upside down, so streching in y direction
2191          * doesn't cost extra time
2192          *
2193          * However, streching in x direction can be avoided if not necessary
2194          */
2195         for(row = drect->y1; row < drect->y2; row++) {
2196             if( (xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) {
2197                 /* Well, that stuff works, but it's very slow.
2198                  * find a better way instead
2199                  */
2200                 UINT col;
2201
2202                 if(!warned) {
2203                     warned = TRUE;
2204                     FIXME("Doing a pixel by pixel render target -> texture copy, expect performance issues\n");
2205                 }
2206
2207                 for(col = drect->x1; col < drect->x2; col++) {
2208                     glCopyTexSubImage2D(This->glDescription.target,
2209                                         This->glDescription.level,
2210                                         drect->x1 + col, row, /* xoffset, yoffset */
2211                                         srect->x1 + col * xrel, yoffset - (int) (row * yrel),
2212                                         1, 1);
2213                 }
2214             } else {
2215                 glCopyTexSubImage2D(This->glDescription.target,
2216                                     This->glDescription.level,
2217                                     drect->x1, row, /* xoffset, yoffset */
2218                                     srect->x1, yoffset - (int) (row * yrel),
2219                                     drect->x2-drect->x1, 1);
2220             }
2221         }
2222     }
2223
2224     vcheckGLcall("glCopyTexSubImage2D");
2225     LEAVE_GL();
2226 }
2227
2228 /* Uses the hardware to stretch and flip the image */
2229 static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWineD3DSurface *SrcSurface, IWineD3DSwapChainImpl *swapchain, WINED3DRECT *srect, WINED3DRECT *drect, BOOL upsidedown) {
2230     GLuint src, backup = 0;
2231     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
2232     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2233     float left, right, top, bottom; /* Texture coordinates */
2234     UINT fbwidth = Src->currentDesc.Width;
2235     UINT fbheight = Src->currentDesc.Height;
2236     GLenum drawBuffer = GL_BACK;
2237
2238     TRACE("Using hwstretch blit\n");
2239     /* Activate the Proper context for reading from the source surface, set it up for blitting */
2240     ENTER_GL();
2241     ActivateContext(myDevice, SrcSurface, CTXUSAGE_BLIT);
2242
2243     /* Try to use an aux buffer for drawing the rectangle. This way it doesn't need restoring.
2244      * This way we don't have to wait for the 2nd readback to finish to leave this function.
2245      */
2246     if(GL_LIMITS(aux_buffers) >= 2) {
2247         /* Got more than one aux buffer? Use the 2nd aux buffer */
2248         drawBuffer = GL_AUX1;
2249     } else if((swapchain || myDevice->offscreenBuffer == GL_BACK) && GL_LIMITS(aux_buffers) >= 1) {
2250         /* Only one aux buffer, but it isn't used (Onscreen rendering, or non-aux orm)? Use it! */
2251         drawBuffer = GL_AUX0;
2252     }
2253
2254     if(!swapchain && wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
2255         glGenTextures(1, &backup);
2256         checkGLcall("glGenTextures\n");
2257         glBindTexture(GL_TEXTURE_2D, backup);
2258         checkGLcall("glBindTexture(Src->glDescription.target, Src->glDescription.textureName)");
2259     } else {
2260         /* Backup the back buffer and copy the source buffer into a texture to draw an upside down stretched quad. If
2261          * we are reading from the back buffer, the backup can be used as source texture
2262          */
2263         if(Src->glDescription.textureName == 0) {
2264             /* Get it a description */
2265             IWineD3DSurface_PreLoad(SrcSurface);
2266         }
2267         glBindTexture(GL_TEXTURE_2D, Src->glDescription.textureName);
2268         checkGLcall("glBindTexture(Src->glDescription.target, Src->glDescription.textureName)");
2269
2270         /* For now invalidate the texture copy of the back buffer. Drawable and sysmem copy are untouched */
2271         Src->Flags &= ~SFLAG_INTEXTURE;
2272     }
2273
2274     glReadBuffer(GL_BACK);
2275     checkGLcall("glReadBuffer(GL_BACK)");
2276
2277     /* TODO: Only back up the part that will be overwritten */
2278     glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
2279                         0, 0 /* read offsets */,
2280                         0, 0,
2281                         fbwidth,
2282                         fbheight);
2283
2284     checkGLcall("glCopyTexSubImage2D");
2285
2286     /* No issue with overriding these - the sampler is dirty due to blit usage */
2287     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2288     checkGLcall("glTexParameteri");
2289     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2290     checkGLcall("glTexParameteri");
2291
2292     if(!swapchain || (IWineD3DSurface *) Src == swapchain->backBuffer[0]) {
2293         src = backup ? backup : Src->glDescription.textureName;
2294     } else {
2295         glReadBuffer(GL_FRONT);
2296         checkGLcall("glReadBuffer(GL_FRONT)");
2297
2298         glGenTextures(1, &src);
2299         checkGLcall("glGenTextures(1, &src)");
2300         glBindTexture(GL_TEXTURE_2D, src);
2301         checkGLcall("glBindTexture(GL_TEXTURE_2D, src)");
2302
2303         /* TODO: Only copy the part that will be read. Use srect->x1, srect->y2 as origin, but with the width watch
2304          * out for power of 2 sizes
2305          */
2306         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Src->pow2Width, Src->pow2Height, 0,
2307                     GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2308         checkGLcall("glTexImage2D");
2309         glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
2310                             0, 0 /* read offsets */,
2311                             0, 0,
2312                             fbwidth,
2313                             fbheight);
2314
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         glReadBuffer(GL_BACK);
2321         checkGLcall("glReadBuffer(GL_BACK)");
2322     }
2323     checkGLcall("glEnd and previous");
2324
2325     left = (float) srect->x1 / (float) Src->pow2Width;
2326     right = (float) srect->x2 / (float) Src->pow2Width;
2327
2328     if(upsidedown) {
2329         top = (float) (Src->currentDesc.Height - srect->y1) / (float) Src->pow2Height;
2330         bottom = (float) (Src->currentDesc.Height - srect->y2) / (float) Src->pow2Height;
2331     } else {
2332         top = (float) (Src->currentDesc.Height - srect->y2) / (float) Src->pow2Height;
2333         bottom = (float) (Src->currentDesc.Height - srect->y1) / (float) Src->pow2Height;
2334     }
2335
2336     /* draw the source texture stretched and upside down. The correct surface is bound already */
2337     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
2338     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
2339
2340     glDrawBuffer(drawBuffer);
2341     glReadBuffer(drawBuffer);
2342
2343     glBegin(GL_QUADS);
2344         /* bottom left */
2345         glTexCoord2f(left, bottom);
2346         glVertex2i(0, fbheight);
2347
2348         /* top left */
2349         glTexCoord2f(left, top);
2350         glVertex2i(0, fbheight - drect->y2 - drect->y1);
2351
2352         /* top right */
2353         glTexCoord2f(right, top);
2354         glVertex2i(drect->x2 - drect->x1, fbheight - drect->y2 - drect->y1);
2355
2356         /* bottom right */
2357         glTexCoord2f(right, bottom);
2358         glVertex2i(drect->x2 - drect->x1, fbheight);
2359     glEnd();
2360     checkGLcall("glEnd and previous");
2361
2362     /* Now read the stretched and upside down image into the destination texture */
2363     glBindTexture(This->glDescription.target, This->glDescription.textureName);
2364     checkGLcall("glBindTexture");
2365     glCopyTexSubImage2D(This->glDescription.target,
2366                         0,
2367                         drect->x1, drect->y1, /* xoffset, yoffset */
2368                         0, 0, /* We blitted the image to the origin */
2369                         drect->x2 - drect->x1, drect->y2 - drect->y1);
2370     checkGLcall("glCopyTexSubImage2D");
2371
2372     /* Write the back buffer backup back */
2373     glBindTexture(GL_TEXTURE_2D, backup ? backup : Src->glDescription.textureName);
2374     checkGLcall("glBindTexture(GL_TEXTURE_2D, Src->glDescription.textureName)");
2375
2376     if(drawBuffer == GL_BACK) {
2377         glBegin(GL_QUADS);
2378             /* top left */
2379             glTexCoord2f(0.0, (float) fbheight / (float) Src->pow2Height);
2380             glVertex2i(0, 0);
2381
2382             /* bottom left */
2383             glTexCoord2f(0.0, 0.0);
2384             glVertex2i(0, fbheight);
2385
2386             /* bottom right */
2387             glTexCoord2f((float) fbwidth / (float) Src->pow2Width, 0.0);
2388             glVertex2i(fbwidth, Src->currentDesc.Height);
2389
2390             /* top right */
2391             glTexCoord2f((float) fbwidth / (float) Src->pow2Width, (float) fbheight / (float) Src->pow2Height);
2392             glVertex2i(fbwidth, 0);
2393         glEnd();
2394     } else {
2395         /* Restore the old draw buffer */
2396         glDrawBuffer(GL_BACK);
2397     }
2398
2399     /* Cleanup */
2400     if(src != Src->glDescription.textureName && src != backup) {
2401         glDeleteTextures(1, &src);
2402         checkGLcall("glDeleteTextures(1, &src)");
2403     }
2404     if(backup) {
2405         glDeleteTextures(1, &backup);
2406         checkGLcall("glDeleteTextures(1, &backup)");
2407     }
2408     LEAVE_GL();
2409 }
2410
2411 /* Not called from the VTable */
2412 static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
2413     WINED3DRECT rect;
2414     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
2415     IWineD3DSwapChainImpl *srcSwapchain = NULL, *dstSwapchain = NULL;
2416     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2417     BOOL SrcOK = TRUE;
2418
2419     TRACE("(%p)->(%p,%p,%p,%08x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2420
2421     /* Get the swapchain. One of the surfaces has to be a primary surface */
2422     IWineD3DSurface_GetContainer( (IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&dstSwapchain);
2423     if(dstSwapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) dstSwapchain);
2424     if(Src) {
2425         IWineD3DSurface_GetContainer( (IWineD3DSurface *) Src, &IID_IWineD3DSwapChain, (void **)&srcSwapchain);
2426         if(srcSwapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) srcSwapchain);
2427     }
2428
2429     /* Early sort out of cases where no render target is used */
2430     if(!dstSwapchain && !srcSwapchain &&
2431         SrcSurface != myDevice->render_targets[0] && This != (IWineD3DSurfaceImpl *) myDevice->render_targets[0]) {
2432         TRACE("No surface is render target, not using hardware blit. Src = %p, dst = %p\n", Src, This);
2433         return WINED3DERR_INVALIDCALL;
2434     }
2435
2436     /* No destination color keying supported */
2437     if(Flags & (DDBLT_KEYDEST | DDBLT_KEYDESTOVERRIDE)) {
2438         /* Can we support that with glBlendFunc if blitting to the frame buffer? */
2439         TRACE("Destination color key not supported in accelerated Blit, falling back to software\n");
2440         return WINED3DERR_INVALIDCALL;
2441     }
2442
2443     if (DestRect) {
2444         rect.x1 = DestRect->left;
2445         rect.y1 = DestRect->top;
2446         rect.x2 = DestRect->right;
2447         rect.y2 = DestRect->bottom;
2448     } else {
2449         rect.x1 = 0;
2450         rect.y1 = 0;
2451         rect.x2 = This->currentDesc.Width;
2452         rect.y2 = This->currentDesc.Height;
2453     }
2454
2455     /* The only case where both surfaces on a swapchain are supported is a back buffer -> front buffer blit on the same swapchain */
2456     if(dstSwapchain && dstSwapchain == srcSwapchain) {
2457         /* Half-life does a Blt from the back buffer to the front buffer,
2458          * Full surface size, no flags... Use present instead
2459          */
2460
2461         /* Check rects - IWineD3DDevice_Present doesn't handle them */
2462         if( SrcRect ) {
2463             if( (SrcRect->left == 0) && (SrcRect->top == 0) &&
2464                 (SrcRect->right == Src->currentDesc.Width) && (SrcRect->bottom == Src->currentDesc.Height) ) {
2465                 SrcOK = TRUE;
2466             }
2467         } else {
2468             SrcOK = TRUE;
2469         }
2470
2471         /* Check the Destination rect and the surface sizes */
2472         if(SrcOK &&
2473            (rect.x1 == 0) && (rect.y1 == 0) &&
2474            (rect.x2 ==  This->currentDesc.Width) && (rect.y2 == This->currentDesc.Height) &&
2475            (This->currentDesc.Width == Src->currentDesc.Width) &&
2476            (This->currentDesc.Height == Src->currentDesc.Height)) {
2477             /* These flags are unimportant for the flag check, remove them */
2478
2479             if((Flags & ~(DDBLT_DONOTWAIT | DDBLT_WAIT)) == 0) {
2480                 if( dstSwapchain->backBuffer && ((IWineD3DSurface *) This == dstSwapchain->frontBuffer) &&
2481                     SrcSurface == dstSwapchain->backBuffer[0] ) {
2482
2483                     WINED3DSWAPEFFECT orig_swap = dstSwapchain->presentParms.SwapEffect;
2484
2485                     /* The idea behind this is that a glReadPixels and a glDrawPixels call
2486                      * take very long, while a flip is fast.
2487                      * This applies to Half-Life, which does such Blts every time it finished
2488                      * a frame, and to Prince of Persia 3D, which uses this to draw at least the main
2489                      * menu. This is also used by all apps when they do windowed rendering
2490                      *
2491                      * The problem is that flipping is not really the same as copying. After a
2492                      * Blt the front buffer is a copy of the back buffer, and the back buffer is
2493                      * untouched. Therefore it's necessary to override the swap effect
2494                      * and to set it back after the flip.
2495                      */
2496
2497                     dstSwapchain->presentParms.SwapEffect = WINED3DSWAPEFFECT_COPY;
2498
2499                     TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n");
2500                     IWineD3DDevice_Present((IWineD3DDevice *) This->resource.wineD3DDevice,
2501                                             NULL, NULL, 0, NULL);
2502
2503                     dstSwapchain->presentParms.SwapEffect = orig_swap;
2504
2505                     return WINED3D_OK;
2506                 }
2507             }
2508         }
2509
2510         TRACE("Unsupported blit between buffers on the same swapchain\n");
2511         return WINED3DERR_INVALIDCALL;
2512     } else if((dstSwapchain || This == (IWineD3DSurfaceImpl *) myDevice->render_targets[0]) &&
2513               (srcSwapchain || SrcSurface == myDevice->render_targets[0]) ) {
2514         ERR("Can't perform hardware blit between 2 different swapchains, falling back to software\n");
2515         return WINED3DERR_INVALIDCALL;
2516     }
2517
2518     if(srcSwapchain || SrcSurface == myDevice->render_targets[0]) {
2519         /* Blit from render target to texture */
2520         WINED3DRECT srect;
2521         BOOL upsideDown, stretchx;
2522
2523         if(Flags & (DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE)) {
2524             TRACE("Color keying not supported by frame buffer to texture blit\n");
2525             return WINED3DERR_INVALIDCALL;
2526             /* Destination color key is checked above */
2527         }
2528
2529         /* Call preload for the surface to make sure it isn't dirty */
2530         IWineD3DSurface_PreLoad((IWineD3DSurface *) This);
2531
2532         /* Make sure that the top pixel is always above the bottom pixel, and keep a seperate upside down flag
2533             * glCopyTexSubImage is a bit picky about the parameters we pass to it
2534             */
2535         if(SrcRect) {
2536             if(SrcRect->top < SrcRect->bottom) {
2537                 srect.y1 = SrcRect->top;
2538                 srect.y2 = SrcRect->bottom;
2539                 upsideDown = FALSE;
2540             } else {
2541                 srect.y1 = SrcRect->bottom;
2542                 srect.y2 = SrcRect->top;
2543                 upsideDown = TRUE;
2544             }
2545             srect.x1 = SrcRect->left;
2546             srect.x2 = SrcRect->right;
2547         } else {
2548             srect.x1 = 0;
2549             srect.y1 = 0;
2550             srect.x2 = Src->currentDesc.Width;
2551             srect.y2 = Src->currentDesc.Height;
2552             upsideDown = FALSE;
2553         }
2554         if(rect.x1 > rect.x2) {
2555             UINT tmp = rect.x2;
2556             rect.x2 = rect.x1;
2557             rect.x1 = tmp;
2558             upsideDown = !upsideDown;
2559         }
2560         if(!srcSwapchain) {
2561             TRACE("Reading from an offscreen target\n");
2562             upsideDown = !upsideDown;
2563         }
2564
2565         if(rect.x2 - rect.x1 != srect.x2 - srect.x1) {
2566             stretchx = TRUE;
2567         } else {
2568             stretchx = FALSE;
2569         }
2570
2571         /* Blt is a pretty powerful call, while glCopyTexSubImage2D is not. glCopyTexSubImage cannot
2572          * flip the image nor scale it. If GL_EXT_framebuffer_blit is available it can be used(hopefully,
2573          * not implemented by now). Otherwise:
2574          *
2575          * -> If the app asks for a unscaled, upside down copy, just perform one glCopyTexSubImage2D call
2576          * -> If the app wants a image width an unscaled width, copy it line per line
2577          * -> If the app wants a image that is scaled on the x axis, and the destination rectangle is smaller
2578          *    than the frame buffer, draw an upside down scaled image onto the fb, read it back and restore the
2579          *    back buffer. This is slower than reading line per line, thus not used for flipping
2580          * -> If the app wants a scaled image with a dest rect that is bigger than the fb, it has to be copied
2581          *    pixel by pixel
2582          */
2583         if(FALSE /* GL_SUPPORT(EXT_FRAMEBUFFER_BLIT) */) {
2584             TRACE("Using GL_EXT_framebuffer_blit for copying\n");
2585         } else if((!stretchx) || rect.x2 - rect.x1 > Src->currentDesc.Width ||
2586                                     rect.y2 - rect.y1 > Src->currentDesc.Height) {
2587             TRACE("No stretching in x direction, using direct framebuffer -> texture copy\n");
2588             fb_copy_to_texture_direct(This, SrcSurface, srcSwapchain, &srect, &rect, upsideDown);
2589         } else {
2590             TRACE("Using hardware stretching to flip / stretch the texture\n");
2591             fb_copy_to_texture_hwstretch(This, SrcSurface, srcSwapchain, &srect, &rect, upsideDown);
2592         }
2593
2594         if(!(This->Flags & SFLAG_DONOTFREE)) {
2595             HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
2596             This->resource.allocatedMemory = NULL;
2597         } else {
2598             This->Flags &= ~SFLAG_INSYSMEM;
2599         }
2600         /* The texture is now most up to date - If the surface is a render target and has a drawable, this
2601          * path is never entered
2602          */
2603         This->Flags |= SFLAG_INTEXTURE;
2604
2605         return WINED3D_OK;
2606     } else if(Src) {
2607         /* Blit from offscreen surface to render target */
2608         float glTexCoord[4];
2609         DWORD oldCKeyFlags = Src->CKeyFlags;
2610         DDCOLORKEY oldBltCKey = This->SrcBltCKey;
2611         RECT SourceRectangle;
2612         GLint oldDraw;
2613
2614         TRACE("Blt from surface %p to rendertarget %p\n", Src, This);
2615
2616         if(SrcRect) {
2617             SourceRectangle.left = SrcRect->left;
2618             SourceRectangle.right = SrcRect->right;
2619             SourceRectangle.top = SrcRect->top;
2620             SourceRectangle.bottom = SrcRect->bottom;
2621         } else {
2622             SourceRectangle.left = 0;
2623             SourceRectangle.right = Src->currentDesc.Width;
2624             SourceRectangle.top = 0;
2625             SourceRectangle.bottom = Src->currentDesc.Height;
2626         }
2627
2628         if(!CalculateTexRect(Src, &SourceRectangle, glTexCoord)) {
2629             /* Fall back to software */
2630             WARN("(%p) Source texture area (%d,%d)-(%d,%d) is too big\n", Src,
2631                     SourceRectangle.left, SourceRectangle.top,
2632                     SourceRectangle.right, SourceRectangle.bottom);
2633             return WINED3DERR_INVALIDCALL;
2634         }
2635
2636         /* Color keying: Check if we have to do a color keyed blt,
2637          * and if not check if a color key is activated.
2638          *
2639          * Just modify the color keying parameters in the surface and restore them afterwards
2640          * The surface keeps track of the color key last used to load the opengl surface.
2641          * PreLoad will catch the change to the flags and color key and reload if neccessary.
2642          */
2643         if(Flags & DDBLT_KEYSRC) {
2644             /* Use color key from surface */
2645         } else if(Flags & DDBLT_KEYSRCOVERRIDE) {
2646             /* Use color key from DDBltFx */
2647             Src->CKeyFlags |= DDSD_CKSRCBLT;
2648             This->SrcBltCKey = DDBltFx->ddckSrcColorkey;
2649         } else {
2650             /* Do not use color key */
2651             Src->CKeyFlags &= ~DDSD_CKSRCBLT;
2652         }
2653
2654         /* Now load the surface */
2655         IWineD3DSurface_PreLoad((IWineD3DSurface *) Src);
2656
2657         ENTER_GL();
2658
2659         /* Activate the destination context, set it up for blitting */
2660         ActivateContext(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT);
2661
2662         glGetIntegerv(GL_DRAW_BUFFER, &oldDraw);
2663         if(This == (IWineD3DSurfaceImpl *) dstSwapchain->frontBuffer) {
2664             TRACE("Drawing to front buffer\n");
2665             glDrawBuffer(GL_FRONT);
2666             checkGLcall("glDrawBuffer GL_FRONT");
2667         }
2668
2669         /* Bind the texture */
2670         glBindTexture(GL_TEXTURE_2D, Src->glDescription.textureName);
2671         checkGLcall("glBindTexture");
2672
2673         /* No filtering for blts */
2674         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2675                         GL_NEAREST);
2676         checkGLcall("glTexParameteri");
2677         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2678                         GL_NEAREST);
2679         checkGLcall("glTexParameteri");
2680         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
2681         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
2682         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2683         checkGLcall("glTexEnvi");
2684
2685         /* This is for color keying */
2686         if(Flags & (DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE)) {
2687             glEnable(GL_ALPHA_TEST);
2688             checkGLcall("glEnable GL_ALPHA_TEST");
2689             glAlphaFunc(GL_NOTEQUAL, 0.0);
2690             checkGLcall("glAlphaFunc\n");
2691         } else {
2692             glDisable(GL_ALPHA_TEST);
2693             checkGLcall("glDisable GL_ALPHA_TEST");
2694         }
2695
2696         /* Draw a textured quad
2697             */
2698         glBegin(GL_QUADS);
2699
2700         glColor3d(1.0f, 1.0f, 1.0f);
2701         glTexCoord2f(glTexCoord[0], glTexCoord[2]);
2702         glVertex3f(rect.x1,
2703                     rect.y1,
2704                     0.0);
2705
2706         glTexCoord2f(glTexCoord[0], glTexCoord[3]);
2707         glVertex3f(rect.x1, rect.y2, 0.0);
2708
2709         glTexCoord2f(glTexCoord[1], glTexCoord[3]);
2710         glVertex3f(rect.x2,
2711                     rect.y2,
2712                     0.0);
2713
2714         glTexCoord2f(glTexCoord[1], glTexCoord[2]);
2715         glVertex3f(rect.x2,
2716                     rect.y1,
2717                     0.0);
2718         glEnd();
2719         checkGLcall("glEnd");
2720
2721         if(Flags & (DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE)) {
2722             glDisable(GL_ALPHA_TEST);
2723             checkGLcall("glDisable(GL_ALPHA_TEST)");
2724         }
2725
2726         /* Unbind the texture */
2727         glBindTexture(GL_TEXTURE_2D, 0);
2728         checkGLcall("glEnable glBindTexture");
2729
2730         if(This == (IWineD3DSurfaceImpl *) dstSwapchain->frontBuffer && oldDraw == GL_BACK) {
2731             glDrawBuffer(oldDraw);
2732         }
2733         /* Restore the color key parameters */
2734         Src->CKeyFlags = oldCKeyFlags;
2735         This->SrcBltCKey = oldBltCKey;
2736
2737         LEAVE_GL();
2738
2739         /* TODO: If the surface is locked often, perform the Blt in software on the memory instead */
2740         This->Flags &= ~SFLAG_INSYSMEM;
2741         /* The surface is now in the drawable. On onscreen surfaces or without fbos the texture
2742          * is outdated now
2743          */
2744         if(dstSwapchain || wined3d_settings.offscreen_rendering_mode != ORM_FBO) {
2745             This->Flags |= SFLAG_INDRAWABLE;
2746             This->Flags &= ~SFLAG_INTEXTURE;
2747         } else {
2748             This->Flags |= SFLAG_INTEXTURE;
2749         }
2750
2751         return WINED3D_OK;
2752     } else {
2753         /* Source-Less Blit to render target */
2754         if (Flags & DDBLT_COLORFILL) {
2755             /* This is easy to handle for the D3D Device... */
2756             DWORD color;
2757
2758             TRACE("Colorfill\n");
2759
2760             /* The color as given in the Blt function is in the format of the frame-buffer...
2761              * 'clear' expect it in ARGB format => we need to do some conversion :-)
2762              */
2763             if (This->resource.format == WINED3DFMT_P8) {
2764                 if (This->palette) {
2765                     color = ((0xFF000000) |
2766                             (This->palette->palents[DDBltFx->u5.dwFillColor].peRed << 16) |
2767                             (This->palette->palents[DDBltFx->u5.dwFillColor].peGreen << 8) |
2768                             (This->palette->palents[DDBltFx->u5.dwFillColor].peBlue));
2769                 } else {
2770                     color = 0xFF000000;
2771                 }
2772             }
2773             else if (This->resource.format == WINED3DFMT_R5G6B5) {
2774                 if (DDBltFx->u5.dwFillColor == 0xFFFF) {
2775                     color = 0xFFFFFFFF;
2776                 } else {
2777                     color = ((0xFF000000) |
2778                             ((DDBltFx->u5.dwFillColor & 0xF800) << 8) |
2779                             ((DDBltFx->u5.dwFillColor & 0x07E0) << 5) |
2780                             ((DDBltFx->u5.dwFillColor & 0x001F) << 3));
2781                 }
2782             }
2783             else if ((This->resource.format == WINED3DFMT_R8G8B8) ||
2784                     (This->resource.format == WINED3DFMT_X8R8G8B8) ) {
2785                 color = 0xFF000000 | DDBltFx->u5.dwFillColor;
2786             }
2787             else if (This->resource.format == WINED3DFMT_A8R8G8B8) {
2788                 color = DDBltFx->u5.dwFillColor;
2789             }
2790             else {
2791                 ERR("Wrong surface type for BLT override(Format doesn't match) !\n");
2792                 return WINED3DERR_INVALIDCALL;
2793             }
2794
2795             TRACE("Calling GetSwapChain with mydevice = %p\n", myDevice);
2796             if(dstSwapchain && dstSwapchain->backBuffer && This == (IWineD3DSurfaceImpl*) dstSwapchain->backBuffer[0]) {
2797                 glDrawBuffer(GL_BACK);
2798                 checkGLcall("glDrawBuffer(GL_BACK)");
2799             } else if (dstSwapchain && This == (IWineD3DSurfaceImpl*) dstSwapchain->frontBuffer) {
2800                 glDrawBuffer(GL_FRONT);
2801                 checkGLcall("glDrawBuffer(GL_FRONT)");
2802             } else if(This == (IWineD3DSurfaceImpl *) myDevice->render_targets[0]) {
2803                 glDrawBuffer(myDevice->offscreenBuffer);
2804                 checkGLcall("glDrawBuffer(myDevice->offscreenBuffer3)");
2805             } else {
2806                 TRACE("Surface is higher back buffer, falling back to software\n");
2807                 return WINED3DERR_INVALIDCALL;
2808             }
2809
2810             TRACE("(%p) executing Render Target override, color = %x\n", This, color);
2811
2812             IWineD3DDevice_Clear( (IWineD3DDevice *) myDevice,
2813                                 1 /* Number of rectangles */,
2814                                 &rect,
2815                                 WINED3DCLEAR_TARGET,
2816                                 color,
2817                                 0.0 /* Z */,
2818                                 0 /* Stencil */);
2819
2820             /* Restore the original draw buffer */
2821             if(!dstSwapchain) {
2822                 glDrawBuffer(myDevice->offscreenBuffer);
2823             } else if(dstSwapchain->backBuffer && dstSwapchain->backBuffer[0]) {
2824                 glDrawBuffer(GL_BACK);
2825             }
2826             vcheckGLcall("glDrawBuffer");
2827
2828             return WINED3D_OK;
2829         }
2830     }
2831
2832     /* Default: Fall back to the generic blt. Not an error, a TRACE is enough */
2833     TRACE("Didn't find any usable render target setup for hw blit, falling back to software\n");
2834     return WINED3DERR_INVALIDCALL;
2835 }
2836
2837 static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
2838     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2839     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2840     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
2841     TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2842     TRACE("(%p): Usage is %s\n", This, debug_d3dusage(This->resource.usage));
2843
2844     /* Accessing the depth stencil is supposed to fail between a BeginScene and EndScene pair */
2845     if(myDevice->inScene &&
2846        (iface == myDevice->stencilBufferTarget ||
2847        (SrcSurface && SrcSurface == myDevice->stencilBufferTarget))) {
2848         TRACE("Attempt to access the depth stencil surface in a BeginScene / EndScene pair, returning WINED3DERR_INVALIDCALL\n");
2849         return WINED3DERR_INVALIDCALL;
2850     }
2851
2852     /* Special cases for RenderTargets */
2853     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
2854         ( Src && (Src->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
2855         if(IWineD3DSurfaceImpl_BltOverride(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx) == WINED3D_OK) return WINED3D_OK;
2856     }
2857
2858     /* For the rest call the X11 surface implementation.
2859      * For RenderTargets this should be implemented OpenGL accelerated in BltOverride,
2860      * other Blts are rather rare
2861      */
2862     return IWineGDISurfaceImpl_Blt(iface, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
2863 }
2864
2865 HRESULT WINAPI IWineD3DSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD Flags) {
2866     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2867     TRACE("(%p)->(%x)\n", This, Flags);
2868
2869     switch (Flags)
2870     {
2871     case DDGBS_CANBLT:
2872     case DDGBS_ISBLTDONE:
2873         return DD_OK;
2874
2875     default:
2876         return DDERR_INVALIDPARAMS;
2877     }
2878 }
2879
2880 HRESULT WINAPI IWineD3DSurfaceImpl_GetFlipStatus(IWineD3DSurface *iface, DWORD Flags) {
2881     /* XXX: DDERR_INVALIDSURFACETYPE */
2882
2883     TRACE("(%p)->(%08x)\n",iface,Flags);
2884     switch (Flags) {
2885     case DDGFS_CANFLIP:
2886     case DDGFS_ISFLIPDONE:
2887         return DD_OK;
2888
2889     default:
2890         return DDERR_INVALIDPARAMS;
2891     }
2892 }
2893
2894 HRESULT WINAPI IWineD3DSurfaceImpl_IsLost(IWineD3DSurface *iface) {
2895     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2896     TRACE("(%p)\n", This);
2897
2898     return This->Flags & SFLAG_LOST ? DDERR_SURFACELOST : WINED3D_OK;
2899 }
2900
2901 HRESULT WINAPI IWineD3DSurfaceImpl_Restore(IWineD3DSurface *iface) {
2902     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2903     TRACE("(%p)\n", This);
2904
2905     /* So far we don't lose anything :) */
2906     This->Flags &= ~SFLAG_LOST;
2907     return WINED3D_OK;
2908 }
2909
2910 HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty, IWineD3DSurface *Source, RECT *rsrc, DWORD trans) {
2911     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2912     IWineD3DSurfaceImpl *srcImpl = (IWineD3DSurfaceImpl *) Source;
2913     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
2914     TRACE("(%p)->(%d, %d, %p, %p, %08x\n", iface, dstx, dsty, Source, rsrc, trans);
2915
2916     if(myDevice->inScene &&
2917        (iface == myDevice->stencilBufferTarget ||
2918        (Source && Source == myDevice->stencilBufferTarget))) {
2919         TRACE("Attempt to access the depth stencil surface in a BeginScene / EndScene pair, returning WINED3DERR_INVALIDCALL\n");
2920         return WINED3DERR_INVALIDCALL;
2921     }
2922
2923     /* Special cases for RenderTargets */
2924     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
2925         ( srcImpl && (srcImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
2926
2927         RECT SrcRect, DstRect;
2928         DWORD Flags=0;
2929
2930         if(rsrc) {
2931             SrcRect.left = rsrc->left;
2932             SrcRect.top= rsrc->top;
2933             SrcRect.bottom = rsrc->bottom;
2934             SrcRect.right = rsrc->right;
2935         } else {
2936             SrcRect.left = 0;
2937             SrcRect.top = 0;
2938             SrcRect.right = srcImpl->currentDesc.Width;
2939             SrcRect.bottom = srcImpl->currentDesc.Height;
2940         }
2941
2942         DstRect.left = dstx;
2943         DstRect.top=dsty;
2944         DstRect.right = dstx + SrcRect.right - SrcRect.left;
2945         DstRect.bottom = dsty + SrcRect.bottom - SrcRect.top;
2946
2947         /* Convert BltFast flags into Btl ones because it is called from SurfaceImpl_Blt as well */
2948         if(trans & DDBLTFAST_SRCCOLORKEY)
2949             Flags |= DDBLT_KEYSRC;
2950         if(trans & DDBLTFAST_DESTCOLORKEY)
2951             Flags |= DDBLT_KEYDEST;
2952         if(trans & DDBLTFAST_WAIT)
2953             Flags |= DDBLT_WAIT;
2954         if(trans & DDBLTFAST_DONOTWAIT)
2955             Flags |= DDBLT_DONOTWAIT;
2956
2957         if(IWineD3DSurfaceImpl_BltOverride(This, &DstRect, Source, &SrcRect, Flags, NULL) == WINED3D_OK) return WINED3D_OK;
2958     }
2959
2960
2961     return IWineGDISurfaceImpl_BltFast(iface, dstx, dsty, Source, rsrc, trans);
2962 }
2963
2964 HRESULT WINAPI IWineD3DSurfaceImpl_GetPalette(IWineD3DSurface *iface, IWineD3DPalette **Pal) {
2965     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2966     TRACE("(%p)->(%p)\n", This, Pal);
2967
2968     *Pal = (IWineD3DPalette *) This->palette;
2969     return DD_OK;
2970 }
2971
2972 HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) {
2973     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2974     RGBQUAD col[256];
2975     IWineD3DPaletteImpl *pal = This->palette;
2976     unsigned int n;
2977     TRACE("(%p)\n", This);
2978
2979     if(This->resource.format == WINED3DFMT_P8 ||
2980        This->resource.format == WINED3DFMT_A8P8)
2981     {
2982         if(!This->Flags & SFLAG_INSYSMEM) {
2983             FIXME("Palette changed with surface that does not have an up to date system memory copy\n");
2984         }
2985         TRACE("Dirtifying surface\n");
2986         This->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INDRAWABLE);
2987     }
2988
2989     if(This->Flags & SFLAG_DIBSECTION) {
2990         TRACE("(%p): Updating the hdc's palette\n", This);
2991         for (n=0; n<256; n++) {
2992             if(pal) {
2993                 col[n].rgbRed   = pal->palents[n].peRed;
2994                 col[n].rgbGreen = pal->palents[n].peGreen;
2995                 col[n].rgbBlue  = pal->palents[n].peBlue;
2996             } else {
2997                 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2998                 /* Use the default device palette */
2999                 col[n].rgbRed   = device->palettes[device->currentPalette][n].peRed;
3000                 col[n].rgbGreen = device->palettes[device->currentPalette][n].peGreen;
3001                 col[n].rgbBlue  = device->palettes[device->currentPalette][n].peBlue;
3002             }
3003             col[n].rgbReserved = 0;
3004         }
3005         SetDIBColorTable(This->hDC, 0, 256, col);
3006     }
3007
3008     return WINED3D_OK;
3009 }
3010
3011 HRESULT WINAPI IWineD3DSurfaceImpl_SetPalette(IWineD3DSurface *iface, IWineD3DPalette *Pal) {
3012     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3013     IWineD3DPaletteImpl *PalImpl = (IWineD3DPaletteImpl *) Pal;
3014     TRACE("(%p)->(%p)\n", This, Pal);
3015
3016     if(This->palette != NULL) 
3017         if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
3018             This->palette->Flags &= ~DDPCAPS_PRIMARYSURFACE;
3019
3020     if(PalImpl != NULL) {
3021         if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
3022             /* Set the device's main palette if the palette
3023              * wasn't a primary palette before
3024              */
3025             if(!(PalImpl->Flags & DDPCAPS_PRIMARYSURFACE)) {
3026                 IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
3027                 unsigned int i;
3028
3029                 for(i=0; i < 256; i++) {
3030                     device->palettes[device->currentPalette][i] = PalImpl->palents[i];
3031                 }
3032             }
3033
3034             (PalImpl)->Flags |= DDPCAPS_PRIMARYSURFACE;
3035         }
3036     }
3037     This->palette = PalImpl;
3038
3039     return IWineD3DSurface_RealizePalette(iface);
3040 }
3041
3042 HRESULT WINAPI IWineD3DSurfaceImpl_SetColorKey(IWineD3DSurface *iface, DWORD Flags, DDCOLORKEY *CKey) {
3043     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3044     TRACE("(%p)->(%08x,%p)\n", This, Flags, CKey);
3045
3046     if ((Flags & DDCKEY_COLORSPACE) != 0) {
3047         FIXME(" colorkey value not supported (%08x) !\n", Flags);
3048         return DDERR_INVALIDPARAMS;
3049     }
3050
3051     /* Dirtify the surface, but only if a key was changed */
3052     if(CKey) {
3053         switch (Flags & ~DDCKEY_COLORSPACE) {
3054             case DDCKEY_DESTBLT:
3055                 This->DestBltCKey = *CKey;
3056                 This->CKeyFlags |= DDSD_CKDESTBLT;
3057                 break;
3058
3059             case DDCKEY_DESTOVERLAY:
3060                 This->DestOverlayCKey = *CKey;
3061                 This->CKeyFlags |= DDSD_CKDESTOVERLAY;
3062                 break;
3063
3064             case DDCKEY_SRCOVERLAY:
3065                 This->SrcOverlayCKey = *CKey;
3066                 This->CKeyFlags |= DDSD_CKSRCOVERLAY;
3067                 break;
3068
3069             case DDCKEY_SRCBLT:
3070                 This->SrcBltCKey = *CKey;
3071                 This->CKeyFlags |= DDSD_CKSRCBLT;
3072                 break;
3073         }
3074     }
3075     else {
3076         switch (Flags & ~DDCKEY_COLORSPACE) {
3077             case DDCKEY_DESTBLT:
3078                 This->CKeyFlags &= ~DDSD_CKDESTBLT;
3079                 break;
3080
3081             case DDCKEY_DESTOVERLAY:
3082                 This->CKeyFlags &= ~DDSD_CKDESTOVERLAY;
3083                 break;
3084
3085             case DDCKEY_SRCOVERLAY:
3086                 This->CKeyFlags &= ~DDSD_CKSRCOVERLAY;
3087                 break;
3088
3089             case DDCKEY_SRCBLT:
3090                 This->CKeyFlags &= ~DDSD_CKSRCBLT;
3091                 break;
3092         }
3093     }
3094
3095     return WINED3D_OK;
3096 }
3097
3098 static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) {
3099     /** Check against the maximum texture sizes supported by the video card **/
3100     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3101
3102     TRACE("%p\n", This);
3103     if ((This->pow2Width > GL_LIMITS(texture_size) || This->pow2Height > GL_LIMITS(texture_size)) && !(This->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))) {
3104         /* one of three options
3105         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)
3106         2: Set the texture to the maxium size (bad idea)
3107         3:    WARN and return WINED3DERR_NOTAVAILABLE;
3108         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.
3109         */
3110         WARN("(%p) Creating an oversized surface\n", This);
3111         This->Flags |= SFLAG_OVERSIZE;
3112
3113         /* This will be initialized on the first blt */
3114         This->glRect.left = 0;
3115         This->glRect.top = 0;
3116         This->glRect.right = 0;
3117         This->glRect.bottom = 0;
3118     } else {
3119         /* No oversize, gl rect is the full texture size */
3120         This->Flags &= ~SFLAG_OVERSIZE;
3121         This->glRect.left = 0;
3122         This->glRect.top = 0;
3123         This->glRect.right = This->pow2Width;
3124         This->glRect.bottom = This->pow2Height;
3125     }
3126
3127     return WINED3D_OK;
3128 }
3129
3130 DWORD WINAPI IWineD3DSurfaceImpl_GetPitch(IWineD3DSurface *iface) {
3131     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3132     DWORD ret;
3133     TRACE("(%p)\n", This);
3134
3135     /* DXTn formats don't have exact pitches as they are to the new row of blocks,
3136          where each block is 4x4 pixels, 8 bytes (dxt1) and 16 bytes (dxt2/3/4/5)
3137           ie pitch = (width/4) * bytes per block                                  */
3138     if (This->resource.format == WINED3DFMT_DXT1) /* DXT1 is 8 bytes per block */
3139         ret = ((This->currentDesc.Width + 3) >> 2) << 3;
3140     else if (This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
3141              This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5) /* DXT2/3/4/5 is 16 bytes per block */
3142         ret = ((This->currentDesc.Width + 3) >> 2) << 4;
3143     else {
3144         ret = This->bytesPerPixel * This->currentDesc.Width;  /* Bytes / row */
3145         /* Surfaces are 32 bit aligned */
3146         ret = (ret + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
3147     }
3148     TRACE("(%p) Returning %d\n", This, ret);
3149     return ret;
3150 }
3151
3152 HRESULT WINAPI IWineD3DSurfaceImpl_SetOverlayPosition(IWineD3DSurface *iface, LONG X, LONG Y) {
3153     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3154
3155     FIXME("(%p)->(%d,%d) Stub!\n", This, X, Y);
3156
3157     if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3158     {
3159         TRACE("(%p): Not an overlay surface\n", This);
3160         return DDERR_NOTAOVERLAYSURFACE;
3161     }
3162
3163     return WINED3D_OK;
3164 }
3165
3166 HRESULT WINAPI IWineD3DSurfaceImpl_GetOverlayPosition(IWineD3DSurface *iface, LONG *X, LONG *Y) {
3167     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3168
3169     FIXME("(%p)->(%p,%p) Stub!\n", This, X, Y);
3170
3171     if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3172     {
3173         TRACE("(%p): Not an overlay surface\n", This);
3174         return DDERR_NOTAOVERLAYSURFACE;
3175     }
3176
3177     return WINED3D_OK;
3178 }
3179
3180 HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlayZOrder(IWineD3DSurface *iface, DWORD Flags, IWineD3DSurface *Ref) {
3181     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3182     IWineD3DSurfaceImpl *RefImpl = (IWineD3DSurfaceImpl *) Ref;
3183
3184     FIXME("(%p)->(%08x,%p) Stub!\n", This, Flags, RefImpl);
3185
3186     if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3187     {
3188         TRACE("(%p): Not an overlay surface\n", This);
3189         return DDERR_NOTAOVERLAYSURFACE;
3190     }
3191
3192     return WINED3D_OK;
3193 }
3194
3195 HRESULT WINAPI IWineD3DSurfaceImpl_UpdateOverlay(IWineD3DSurface *iface, RECT *SrcRect, IWineD3DSurface *DstSurface, RECT *DstRect, DWORD Flags, WINEDDOVERLAYFX *FX) {
3196     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3197     IWineD3DSurfaceImpl *Dst = (IWineD3DSurfaceImpl *) DstSurface;
3198     FIXME("(%p)->(%p, %p, %p, %08x, %p)\n", This, SrcRect, Dst, DstRect, Flags, FX);
3199
3200     if(!(This->resource.usage & WINED3DUSAGE_OVERLAY))
3201     {
3202         TRACE("(%p): Not an overlay surface\n", This);
3203         return DDERR_NOTAOVERLAYSURFACE;
3204     }
3205
3206     return WINED3D_OK;
3207 }
3208
3209 const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
3210 {
3211     /* IUnknown */
3212     IWineD3DSurfaceImpl_QueryInterface,
3213     IWineD3DSurfaceImpl_AddRef,
3214     IWineD3DSurfaceImpl_Release,
3215     /* IWineD3DResource */
3216     IWineD3DSurfaceImpl_GetParent,
3217     IWineD3DSurfaceImpl_GetDevice,
3218     IWineD3DSurfaceImpl_SetPrivateData,
3219     IWineD3DSurfaceImpl_GetPrivateData,
3220     IWineD3DSurfaceImpl_FreePrivateData,
3221     IWineD3DSurfaceImpl_SetPriority,
3222     IWineD3DSurfaceImpl_GetPriority,
3223     IWineD3DSurfaceImpl_PreLoad,
3224     IWineD3DSurfaceImpl_GetType,
3225     /* IWineD3DSurface */
3226     IWineD3DSurfaceImpl_GetContainer,
3227     IWineD3DSurfaceImpl_GetDesc,
3228     IWineD3DSurfaceImpl_LockRect,
3229     IWineD3DSurfaceImpl_UnlockRect,
3230     IWineD3DSurfaceImpl_GetDC,
3231     IWineD3DSurfaceImpl_ReleaseDC,
3232     IWineD3DSurfaceImpl_Flip,
3233     IWineD3DSurfaceImpl_Blt,
3234     IWineD3DSurfaceImpl_GetBltStatus,
3235     IWineD3DSurfaceImpl_GetFlipStatus,
3236     IWineD3DSurfaceImpl_IsLost,
3237     IWineD3DSurfaceImpl_Restore,
3238     IWineD3DSurfaceImpl_BltFast,
3239     IWineD3DSurfaceImpl_GetPalette,
3240     IWineD3DSurfaceImpl_SetPalette,
3241     IWineD3DSurfaceImpl_RealizePalette,
3242     IWineD3DSurfaceImpl_SetColorKey,
3243     IWineD3DSurfaceImpl_GetPitch,
3244     IWineD3DSurfaceImpl_SetMem,
3245     IWineD3DSurfaceImpl_SetOverlayPosition,
3246     IWineD3DSurfaceImpl_GetOverlayPosition,
3247     IWineD3DSurfaceImpl_UpdateOverlayZOrder,
3248     IWineD3DSurfaceImpl_UpdateOverlay,
3249     /* Internal use: */
3250     IWineD3DSurfaceImpl_AddDirtyRect,
3251     IWineD3DSurfaceImpl_LoadTexture,
3252     IWineD3DSurfaceImpl_SaveSnapshot,
3253     IWineD3DSurfaceImpl_SetContainer,
3254     IWineD3DSurfaceImpl_SetGlTextureDesc,
3255     IWineD3DSurfaceImpl_GetGlDesc,
3256     IWineD3DSurfaceImpl_GetData,
3257     IWineD3DSurfaceImpl_SetFormat,
3258     IWineD3DSurfaceImpl_PrivateSetup
3259 };