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