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