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