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