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