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