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