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