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