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