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