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