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