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