wined3d: IWineD3DSurface_PreLoad() doesn't do an implicit glBindTexture() anymore.
[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-2008 Stefan Dösinger for CodeWeavers
11  * Copyright 2007-2008 Henri Verbeet
12  * Copyright 2006-2008 Roderick Colenbrander
13  *
14  * This library is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU Lesser General Public
16  * License as published by the Free Software Foundation; either
17  * version 2.1 of the License, or (at your option) any later version.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27  */
28
29 #include "config.h"
30 #include "wine/port.h"
31 #include "wined3d_private.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
34 #define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info
35
36 HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *surf);
37 static void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4], BOOL colorkey);
38 static void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES convert);
39 static inline void clear_unused_channels(IWineD3DSurfaceImpl *This);
40 static void surface_remove_pbo(IWineD3DSurfaceImpl *This);
41
42 static void surface_bind_and_dirtify(IWineD3DSurfaceImpl *This) {
43     int active_sampler;
44
45     /* We don't need a specific texture unit, but after binding the texture the current unit is dirty.
46      * Read the unit back instead of switching to 0, this avoids messing around with the state manager's
47      * gl states. The current texture unit should always be a valid one.
48      *
49      * TODO: Track the current active texture per GL context instead of using glGet
50      */
51     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
52         GLint active_texture;
53         ENTER_GL();
54         glGetIntegerv(GL_ACTIVE_TEXTURE, &active_texture);
55         LEAVE_GL();
56         active_sampler = This->resource.wineD3DDevice->rev_tex_unit_map[active_texture - GL_TEXTURE0_ARB];
57     } else {
58         active_sampler = 0;
59     }
60
61     if (active_sampler != -1) {
62         IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_SAMPLER(active_sampler));
63     }
64     IWineD3DSurface_BindTexture((IWineD3DSurface *)This);
65 }
66
67 /* This function checks if the primary render target uses the 8bit paletted format. */
68 static BOOL primary_render_target_is_p8(IWineD3DDeviceImpl *device)
69 {
70     if (device->render_targets && device->render_targets[0]) {
71         IWineD3DSurfaceImpl* render_target = (IWineD3DSurfaceImpl*)device->render_targets[0];
72         if((render_target->resource.usage & WINED3DUSAGE_RENDERTARGET) && (render_target->resource.format == WINED3DFMT_P8))
73             return TRUE;
74     }
75     return FALSE;
76 }
77
78 /* This call just downloads data, the caller is responsible for activating the
79  * right context and binding the correct texture. */
80 static void surface_download_data(IWineD3DSurfaceImpl *This) {
81     if (0 == This->glDescription.textureName) {
82         ERR("Surface does not have a texture, but SFLAG_INTEXTURE is set\n");
83         return;
84     }
85
86     /* Only support read back of converted P8 surfaces */
87     if(This->Flags & SFLAG_CONVERTED && (This->resource.format != WINED3DFMT_P8)) {
88         FIXME("Read back converted textures unsupported, format=%s\n", debug_d3dformat(This->resource.format));
89         return;
90     }
91
92     ENTER_GL();
93
94     if (This->resource.format == WINED3DFMT_DXT1 ||
95             This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
96             This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5 ||
97             This->resource.format == WINED3DFMT_ATI2N) {
98         if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) { /* We can assume this as the texture would not have been created otherwise */
99             FIXME("(%p) : Attempting to lock a compressed texture when texture compression isn't supported by opengl\n", This);
100         } else {
101             TRACE("(%p) : Calling glGetCompressedTexImageARB level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level,
102                 This->glDescription.glFormat, This->glDescription.glType, This->resource.allocatedMemory);
103
104             if(This->Flags & SFLAG_PBO) {
105                 GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, This->pbo));
106                 checkGLcall("glBindBufferARB");
107                 GL_EXTCALL(glGetCompressedTexImageARB(This->glDescription.target, This->glDescription.level, NULL));
108                 checkGLcall("glGetCompressedTexImageARB()");
109                 GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
110                 checkGLcall("glBindBufferARB");
111             } else {
112                 GL_EXTCALL(glGetCompressedTexImageARB(This->glDescription.target, This->glDescription.level, This->resource.allocatedMemory));
113                 checkGLcall("glGetCompressedTexImageARB()");
114             }
115         }
116         LEAVE_GL();
117     } else {
118         void *mem;
119         GLenum format = This->glDescription.glFormat;
120         GLenum type = This->glDescription.glType;
121         int src_pitch = 0;
122         int dst_pitch = 0;
123
124         /* In case of P8 the index is stored in the alpha component if the primary render target uses P8 */
125         if(This->resource.format == WINED3DFMT_P8 && primary_render_target_is_p8(This->resource.wineD3DDevice)) {
126             format = GL_ALPHA;
127             type = GL_UNSIGNED_BYTE;
128         }
129
130         if (This->Flags & SFLAG_NONPOW2) {
131             unsigned char alignment = This->resource.wineD3DDevice->surface_alignment;
132             src_pitch = This->bytesPerPixel * This->pow2Width;
133             dst_pitch = IWineD3DSurface_GetPitch((IWineD3DSurface *) This);
134             src_pitch = (src_pitch + alignment - 1) & ~(alignment - 1);
135             mem = HeapAlloc(GetProcessHeap(), 0, src_pitch * This->pow2Height);
136         } else {
137             mem = This->resource.allocatedMemory;
138         }
139
140         TRACE("(%p) : Calling glGetTexImage level %d, format %#x, type %#x, data %p\n", This, This->glDescription.level,
141                 format, type, mem);
142
143         if(This->Flags & SFLAG_PBO) {
144             GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, This->pbo));
145             checkGLcall("glBindBufferARB");
146
147             glGetTexImage(This->glDescription.target, This->glDescription.level, format,
148                           type, NULL);
149             checkGLcall("glGetTexImage()");
150
151             GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
152             checkGLcall("glBindBufferARB");
153         } else {
154             glGetTexImage(This->glDescription.target, This->glDescription.level, format,
155                           type, mem);
156             checkGLcall("glGetTexImage()");
157         }
158         LEAVE_GL();
159
160         if (This->Flags & SFLAG_NONPOW2) {
161             LPBYTE src_data, dst_data;
162             int y;
163             /*
164              * Some games (e.g. warhammer 40k) don't work properly with the odd pitches, preventing
165              * the surface pitch from being used to box non-power2 textures. Instead we have to use a hack to
166              * repack the texture so that the bpp * width pitch can be used instead of bpp * pow2width.
167              *
168              * We're doing this...
169              *
170              * instead of boxing the texture :
171              * |<-texture width ->|  -->pow2width|   /\
172              * |111111111111111111|              |   |
173              * |222 Texture 222222| boxed empty  | texture height
174              * |3333 Data 33333333|              |   |
175              * |444444444444444444|              |   \/
176              * -----------------------------------   |
177              * |     boxed  empty | boxed empty  | pow2height
178              * |                  |              |   \/
179              * -----------------------------------
180              *
181              *
182              * we're repacking the data to the expected texture width
183              *
184              * |<-texture width ->|  -->pow2width|   /\
185              * |111111111111111111222222222222222|   |
186              * |222333333333333333333444444444444| texture height
187              * |444444                           |   |
188              * |                                 |   \/
189              * |                                 |   |
190              * |            empty                | pow2height
191              * |                                 |   \/
192              * -----------------------------------
193              *
194              * == is the same as
195              *
196              * |<-texture width ->|    /\
197              * |111111111111111111|
198              * |222222222222222222|texture height
199              * |333333333333333333|
200              * |444444444444444444|    \/
201              * --------------------
202              *
203              * this also means that any references to allocatedMemory should work with the data as if were a
204              * standard texture with a non-power2 width instead of texture boxed up to be a power2 texture.
205              *
206              * internally the texture is still stored in a boxed format so any references to textureName will
207              * get a boxed texture with width pow2width and not a texture of width currentDesc.Width.
208              *
209              * Performance should not be an issue, because applications normally do not lock the surfaces when
210              * rendering. If an app does, the SFLAG_DYNLOCK flag will kick in and the memory copy won't be released,
211              * and doesn't have to be re-read.
212              */
213             src_data = mem;
214             dst_data = This->resource.allocatedMemory;
215             TRACE("(%p) : Repacking the surface data from pitch %d to pitch %d\n", This, src_pitch, dst_pitch);
216             for (y = 1 ; y < This->currentDesc.Height; y++) {
217                 /* skip the first row */
218                 src_data += src_pitch;
219                 dst_data += dst_pitch;
220                 memcpy(dst_data, src_data, dst_pitch);
221             }
222
223             HeapFree(GetProcessHeap(), 0, mem);
224         }
225     }
226
227     /* Surface has now been downloaded */
228     This->Flags |= SFLAG_INSYSMEM;
229 }
230
231 /* This call just uploads data, the caller is responsible for activating the
232  * right context and binding the correct texture. */
233 static void surface_upload_data(IWineD3DSurfaceImpl *This, GLenum internal, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *data) {
234
235     if(This->heightscale != 1.0 && This->heightscale != 0.0) height *= This->heightscale;
236
237     if (This->resource.format == WINED3DFMT_DXT1 ||
238             This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
239             This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5 ||
240             This->resource.format == WINED3DFMT_ATI2N) {
241         if (!GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
242             FIXME("Using DXT1/3/5 without advertized support\n");
243         } else {
244             /* glCompressedTexSubImage2D for uploading and glTexImage2D for allocating does not work well on some drivers(r200 dri, MacOS ATI driver)
245              * glCompressedTexImage2D does not accept NULL pointers. So for compressed textures surface_allocate_surface does nothing, and this
246              * function uses glCompressedTexImage2D instead of the SubImage call
247              */
248             TRACE("(%p) : Calling glCompressedTexSubImage2D w %d, h %d, data %p\n", This, width, height, data);
249             ENTER_GL();
250
251             if(This->Flags & SFLAG_PBO) {
252                 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
253                 checkGLcall("glBindBufferARB");
254                 TRACE("(%p) pbo: %#x, data: %p\n", This, This->pbo, data);
255
256                 GL_EXTCALL(glCompressedTexImage2DARB(This->glDescription.target, This->glDescription.level, internal,
257                         width, height, 0 /* border */, This->resource.size, NULL));
258                 checkGLcall("glCompressedTexSubImage2D");
259
260                 GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
261                 checkGLcall("glBindBufferARB");
262             } else {
263                 GL_EXTCALL(glCompressedTexImage2DARB(This->glDescription.target, This->glDescription.level, internal,
264                         width, height, 0 /* border */, This->resource.size, data));
265                 checkGLcall("glCompressedTexSubImage2D");
266             }
267             LEAVE_GL();
268         }
269     } else {
270         TRACE("(%p) : Calling glTexSubImage2D w %d,  h %d, data, %p\n", This, width, height, data);
271         ENTER_GL();
272
273         if(This->Flags & SFLAG_PBO) {
274             GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
275             checkGLcall("glBindBufferARB");
276             TRACE("(%p) pbo: %#x, data: %p\n", This, This->pbo, data);
277
278             glTexSubImage2D(This->glDescription.target, This->glDescription.level, 0, 0, width, height, format, type, NULL);
279             checkGLcall("glTexSubImage2D");
280
281             GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
282             checkGLcall("glBindBufferARB");
283         }
284         else {
285             glTexSubImage2D(This->glDescription.target, This->glDescription.level, 0, 0, width, height, format, type, data);
286             checkGLcall("glTexSubImage2D");
287         }
288
289         LEAVE_GL();
290     }
291 }
292
293 /* This call just allocates the texture, the caller is responsible for
294  * activating the right context and binding the correct texture. */
295 static void surface_allocate_surface(IWineD3DSurfaceImpl *This, GLenum internal, GLsizei width, GLsizei height, GLenum format, GLenum type) {
296     BOOL enable_client_storage = FALSE;
297     BYTE *mem = NULL;
298
299     if(This->heightscale != 1.0 && This->heightscale != 0.0) height *= This->heightscale;
300
301     TRACE("(%p) : Creating surface (target %#x)  level %d, d3d format %s, internal format %#x, width %d, height %d, gl format %#x, gl type=%#x\n", This,
302             This->glDescription.target, This->glDescription.level, debug_d3dformat(This->resource.format), internal, width, height, format, type);
303
304     if (This->resource.format == WINED3DFMT_DXT1 ||
305             This->resource.format == WINED3DFMT_DXT2 || This->resource.format == WINED3DFMT_DXT3 ||
306             This->resource.format == WINED3DFMT_DXT4 || This->resource.format == WINED3DFMT_DXT5 ||
307             This->resource.format == WINED3DFMT_ATI2N) {
308         /* glCompressedTexImage2D does not accept NULL pointers, so we cannot allocate a compressed texture without uploading data */
309         TRACE("Not allocating compressed surfaces, surface_upload_data will specify them\n");
310
311         /* We have to point GL to the client storage memory here, because upload_data might use a PBO. This means a double upload
312          * once, unfortunately
313          */
314         if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
315             /* Neither NONPOW2, DIBSECTION nor OVERSIZE flags can be set on compressed textures */
316             This->Flags |= SFLAG_CLIENT;
317             mem = (BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
318             ENTER_GL();
319             GL_EXTCALL(glCompressedTexImage2DARB(This->glDescription.target, This->glDescription.level, internal,
320                        width, height, 0 /* border */, This->resource.size, mem));
321             LEAVE_GL();
322         }
323
324         return;
325     }
326
327     ENTER_GL();
328
329     if(GL_SUPPORT(APPLE_CLIENT_STORAGE)) {
330         if(This->Flags & (SFLAG_NONPOW2 | SFLAG_DIBSECTION | SFLAG_OVERSIZE | SFLAG_CONVERTED) || This->resource.allocatedMemory == NULL) {
331             /* In some cases we want to disable client storage.
332              * SFLAG_NONPOW2 has a bigger opengl texture than the client memory, and different pitches
333              * SFLAG_DIBSECTION: Dibsections may have read / write protections on the memory. Avoid issues...
334              * SFLAG_OVERSIZE: The gl texture is smaller than the allocated memory
335              * SFLAG_CONVERTED: The conversion destination memory is freed after loading the surface
336              * allocatedMemory == NULL: Not defined in the extension. Seems to disable client storage effectively
337              */
338             glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
339             checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE)");
340             This->Flags &= ~SFLAG_CLIENT;
341             enable_client_storage = TRUE;
342         } else {
343             This->Flags |= SFLAG_CLIENT;
344
345             /* Point opengl to our allocated texture memory. Do not use resource.allocatedMemory here because
346              * it might point into a pbo. Instead use heapMemory, but get the alignment right.
347              */
348             mem = (BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
349         }
350     }
351     glTexImage2D(This->glDescription.target, This->glDescription.level, internal, width, height, 0, format, type, mem);
352     checkGLcall("glTexImage2D");
353
354     if(enable_client_storage) {
355         glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
356         checkGLcall("glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE)");
357     }
358     LEAVE_GL();
359
360     This->Flags |= SFLAG_ALLOCATED;
361 }
362
363 /* In D3D the depth stencil dimensions have to be greater than or equal to the
364  * render target dimensions. With FBOs, the dimensions have to be an exact match. */
365 /* TODO: We should synchronize the renderbuffer's content with the texture's content. */
366 void surface_set_compatible_renderbuffer(IWineD3DSurface *iface, unsigned int width, unsigned int height) {
367     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
368     renderbuffer_entry_t *entry;
369     GLuint renderbuffer = 0;
370     unsigned int src_width, src_height;
371
372     src_width = This->pow2Width;
373     src_height = This->pow2Height;
374
375     /* A depth stencil smaller than the render target is not valid */
376     if (width > src_width || height > src_height) return;
377
378     /* Remove any renderbuffer set if the sizes match */
379     if (width == src_width && height == src_height) {
380         This->current_renderbuffer = NULL;
381         return;
382     }
383
384     /* Look if we've already got a renderbuffer of the correct dimensions */
385     LIST_FOR_EACH_ENTRY(entry, &This->renderbuffers, renderbuffer_entry_t, entry) {
386         if (entry->width == width && entry->height == height) {
387             renderbuffer = entry->id;
388             This->current_renderbuffer = entry;
389             break;
390         }
391     }
392
393     if (!renderbuffer) {
394         const GlPixelFormatDesc *glDesc;
395         getFormatDescEntry(This->resource.format, &GLINFO_LOCATION, &glDesc);
396
397         GL_EXTCALL(glGenRenderbuffersEXT(1, &renderbuffer));
398         GL_EXTCALL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer));
399         GL_EXTCALL(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, glDesc->glFormat, width, height));
400
401         entry = HeapAlloc(GetProcessHeap(), 0, sizeof(renderbuffer_entry_t));
402         entry->width = width;
403         entry->height = height;
404         entry->id = renderbuffer;
405         list_add_head(&This->renderbuffers, &entry->entry);
406
407         This->current_renderbuffer = entry;
408     }
409
410     checkGLcall("set_compatible_renderbuffer");
411 }
412
413 GLenum surface_get_gl_buffer(IWineD3DSurface *iface, IWineD3DSwapChain *swapchain) {
414     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
415     IWineD3DSwapChainImpl *swapchain_impl = (IWineD3DSwapChainImpl *)swapchain;
416
417     TRACE("(%p) : swapchain %p\n", This, swapchain);
418
419     if (swapchain_impl->backBuffer && swapchain_impl->backBuffer[0] == iface) {
420         TRACE("Returning GL_BACK\n");
421         return GL_BACK;
422     } else if (swapchain_impl->frontBuffer == iface) {
423         TRACE("Returning GL_FRONT\n");
424         return GL_FRONT;
425     }
426
427     FIXME("Higher back buffer, returning GL_BACK\n");
428     return GL_BACK;
429 }
430
431 ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
432     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
433     ULONG ref = InterlockedDecrement(&This->resource.ref);
434     TRACE("(%p) : Releasing from %d\n", This, ref + 1);
435     if (ref == 0) {
436         IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
437         renderbuffer_entry_t *entry, *entry2;
438         TRACE("(%p) : cleaning up\n", This);
439
440         /* Need a context to destroy the texture. Use the currently active render target, but only if
441          * the primary render target exists. Otherwise lastActiveRenderTarget is garbage, see above.
442          * When destroying the primary rt, Uninit3D will activate a context before doing anything
443          */
444         if(device->render_targets && device->render_targets[0]) {
445             ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
446         }
447
448         ENTER_GL();
449         if (This->glDescription.textureName != 0) { /* release the openGL texture.. */
450             TRACE("Deleting texture %d\n", This->glDescription.textureName);
451             glDeleteTextures(1, &This->glDescription.textureName);
452         }
453
454         if(This->Flags & SFLAG_PBO) {
455             /* Delete the PBO */
456             GL_EXTCALL(glDeleteBuffersARB(1, &This->pbo));
457         }
458
459         LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &This->renderbuffers, renderbuffer_entry_t, entry) {
460             GL_EXTCALL(glDeleteRenderbuffersEXT(1, &entry->id));
461             HeapFree(GetProcessHeap(), 0, entry);
462         }
463         LEAVE_GL();
464
465         if(This->Flags & SFLAG_DIBSECTION) {
466             /* Release the DC */
467             SelectObject(This->hDC, This->dib.holdbitmap);
468             DeleteDC(This->hDC);
469             /* Release the DIB section */
470             DeleteObject(This->dib.DIBsection);
471             This->dib.bitmap_data = NULL;
472             This->resource.allocatedMemory = NULL;
473         }
474         if(This->Flags & SFLAG_USERPTR) IWineD3DSurface_SetMem(iface, NULL);
475
476         HeapFree(GetProcessHeap(), 0, This->palette9);
477
478         IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
479
480         if(This->overlay_dest) {
481             list_remove(&This->overlay_entry);
482         }
483
484         TRACE("(%p) Released\n", This);
485         HeapFree(GetProcessHeap(), 0, This);
486
487     }
488     return ref;
489 }
490
491 /* ****************************************************
492    IWineD3DSurface IWineD3DResource parts follow
493    **************************************************** */
494
495 void WINAPI IWineD3DSurfaceImpl_PreLoad(IWineD3DSurface *iface) {
496     /* TODO: check for locks */
497     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
498     IWineD3DBaseTexture *baseTexture = NULL;
499     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
500
501     TRACE("(%p)Checking to see if the container is a base texture\n", This);
502     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
503         TRACE("Passing to container\n");
504         IWineD3DBaseTexture_PreLoad(baseTexture);
505         IWineD3DBaseTexture_Release(baseTexture);
506     } else {
507         TRACE("(%p) : About to load surface\n", This);
508
509         if(!device->isInDraw) {
510             ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
511         }
512
513         if (This->resource.format == WINED3DFMT_P8 || This->resource.format == WINED3DFMT_A8P8) {
514             if(palette9_changed(This)) {
515                 TRACE("Reloading surface because the d3d8/9 palette was changed\n");
516                 /* TODO: This is not necessarily needed with hw palettized texture support */
517                 IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL);
518                 /* Make sure the texture is reloaded because of the palette change, this kills performance though :( */
519                 IWineD3DSurface_ModifyLocation(iface, SFLAG_INTEXTURE, FALSE);
520             }
521         }
522
523         IWineD3DSurface_LoadTexture(iface, FALSE);
524
525         if (This->resource.pool == WINED3DPOOL_DEFAULT) {
526             /* Tell opengl to try and keep this texture in video ram (well mostly) */
527             GLclampf tmp;
528             tmp = 0.9f;
529             ENTER_GL();
530             glPrioritizeTextures(1, &This->glDescription.textureName, &tmp);
531             LEAVE_GL();
532         }
533     }
534     return;
535 }
536
537 static void surface_remove_pbo(IWineD3DSurfaceImpl *This) {
538     This->resource.heapMemory = HeapAlloc(GetProcessHeap() ,0 , This->resource.size + RESOURCE_ALIGNMENT);
539     This->resource.allocatedMemory =
540             (BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
541
542     ENTER_GL();
543     GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
544     checkGLcall("glBindBuffer(GL_PIXEL_UNPACK_BUFFER, This->pbo)");
545     GL_EXTCALL(glGetBufferSubDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0, This->resource.size, This->resource.allocatedMemory));
546     checkGLcall("glGetBufferSubData");
547     GL_EXTCALL(glDeleteBuffersARB(1, &This->pbo));
548     checkGLcall("glDeleteBuffers");
549     LEAVE_GL();
550
551     This->pbo = 0;
552     This->Flags &= ~SFLAG_PBO;
553 }
554
555 static void WINAPI IWineD3DSurfaceImpl_UnLoad(IWineD3DSurface *iface) {
556     IWineD3DBaseTexture *texture = NULL;
557     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
558     renderbuffer_entry_t *entry, *entry2;
559     TRACE("(%p)\n", iface);
560
561     if(This->resource.pool == WINED3DPOOL_DEFAULT) {
562         /* Default pool resources are supposed to be destroyed before Reset is called.
563          * Implicit resources stay however. So this means we have an implicit render target
564          * or depth stencil. The content may be destroyed, but we still have to tear down
565          * opengl resources, so we cannot leave early.
566          *
567          * Put the most up to date surface location into the drawable. D3D-wise this content
568          * is undefined, so it would be nowhere, but that would make the location management
569          * more complicated. The drawable is a sane location, because if we mark sysmem or
570          * texture up to date, drawPrim will copy the uninitialized texture or sysmem to the
571          * uninitialized drawable. That's pointless and we'd have to allocate the texture /
572          * sysmem copy here.
573          */
574         if (This->resource.usage & WINED3DUSAGE_DEPTHSTENCIL) {
575             IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE);
576         } else {
577             IWineD3DSurface_ModifyLocation(iface, SFLAG_INDRAWABLE, TRUE);
578         }
579     } else {
580         /* Load the surface into system memory */
581         IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL);
582         IWineD3DSurface_ModifyLocation(iface, SFLAG_INDRAWABLE, FALSE);
583     }
584     IWineD3DSurface_ModifyLocation(iface, SFLAG_INTEXTURE, FALSE);
585     This->Flags &= ~SFLAG_ALLOCATED;
586
587     /* Destroy PBOs, but load them into real sysmem before */
588     if(This->Flags & SFLAG_PBO) {
589         surface_remove_pbo(This);
590     }
591
592     /* Destroy fbo render buffers. This is needed for implicit render targets, for
593      * all application-created targets the application has to release the surface
594      * before calling _Reset
595      */
596     LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &This->renderbuffers, renderbuffer_entry_t, entry) {
597         ENTER_GL();
598         GL_EXTCALL(glDeleteRenderbuffersEXT(1, &entry->id));
599         LEAVE_GL();
600         list_remove(&entry->entry);
601         HeapFree(GetProcessHeap(), 0, entry);
602     }
603     list_init(&This->renderbuffers);
604     This->current_renderbuffer = NULL;
605
606     /* If we're in a texture, the texture name belongs to the texture. Otherwise,
607      * destroy it
608      */
609     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **) &texture);
610     if(!texture) {
611         ENTER_GL();
612         glDeleteTextures(1, &This->glDescription.textureName);
613         This->glDescription.textureName = 0;
614         LEAVE_GL();
615     } else {
616         IWineD3DBaseTexture_Release(texture);
617     }
618     return;
619 }
620
621 /* ******************************************************
622    IWineD3DSurface IWineD3DSurface parts follow
623    ****************************************************** */
624
625 void WINAPI IWineD3DSurfaceImpl_SetGlTextureDesc(IWineD3DSurface *iface, UINT textureName, int target) {
626     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
627     TRACE("(%p) : setting textureName %u, target %i\n", This, textureName, target);
628     if (This->glDescription.textureName == 0 && textureName != 0) {
629         IWineD3DSurface_ModifyLocation(iface, SFLAG_INTEXTURE, FALSE);
630         if((This->Flags & SFLAG_LOCATIONS) == 0) {
631             /* In 1.0-rc4 and earlier, AddDirtyRect was called in the place of this if condition.
632              * This had the problem that a correctly set INDRAWABLE flag was removed if the PreLoad
633              * during the offscreen rendering readback triggered the creation of the GL texture.
634              * The change intended to keep the INDRAWABLE intact. To prevent unintended side effects
635              * before release, set the INSYSMEM flag like the old AddDirtyRect did.
636              */
637             WARN("Wine 1.0 safety path hit\n");
638             This->Flags |= SFLAG_INSYSMEM;
639         }
640     }
641     if(target == GL_TEXTURE_RECTANGLE_ARB && This->glDescription.target != target) {
642         This->Flags &= ~SFLAG_NORMCOORD;
643     } else if(This->glDescription.target == GL_TEXTURE_RECTANGLE_ARB && target != GL_TEXTURE_RECTANGLE_ARB) {
644         This->Flags |= SFLAG_NORMCOORD;
645     }
646     This->glDescription.textureName = textureName;
647     This->glDescription.target      = target;
648     This->Flags &= ~SFLAG_ALLOCATED;
649 }
650
651 void WINAPI IWineD3DSurfaceImpl_GetGlDesc(IWineD3DSurface *iface, glDescriptor **glDescription) {
652     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
653     TRACE("(%p) : returning %p\n", This, &This->glDescription);
654     *glDescription = &This->glDescription;
655 }
656
657 /* TODO: think about moving this down to resource? */
658 const void *WINAPI IWineD3DSurfaceImpl_GetData(IWineD3DSurface *iface) {
659     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
660     /* 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 future  */
661     if (This->resource.pool != WINED3DPOOL_SYSTEMMEM) {
662         FIXME(" (%p)Attempting to get system memory for a non-system memory texture\n", iface);
663     }
664     return (CONST void*)(This->resource.allocatedMemory);
665 }
666
667 /* Read the framebuffer back into the surface */
668 static void read_from_framebuffer(IWineD3DSurfaceImpl *This, CONST RECT *rect, void *dest, UINT pitch) {
669     IWineD3DSwapChainImpl *swapchain;
670     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
671     BYTE *mem;
672     GLint fmt;
673     GLint type;
674     BYTE *row, *top, *bottom;
675     int i;
676     BOOL bpp;
677     RECT local_rect;
678     BOOL srcIsUpsideDown;
679
680     if(wined3d_settings.rendertargetlock_mode == RTL_DISABLE) {
681         static BOOL warned = FALSE;
682         if(!warned) {
683             ERR("The application tries to lock the render target, but render target locking is disabled\n");
684             warned = TRUE;
685         }
686         return;
687     }
688
689     IWineD3DSurface_GetContainer((IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&swapchain);
690     /* Activate the surface. Set it up for blitting now, although not necessarily needed for LockRect.
691      * Certain graphics drivers seem to dislike some enabled states when reading from opengl, the blitting usage
692      * should help here. Furthermore unlockrect will need the context set up for blitting. The context manager will find
693      * context->last_was_blit set on the unlock.
694      */
695     ActivateContext(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT);
696     ENTER_GL();
697
698     /* Select the correct read buffer, and give some debug output.
699      * There is no need to keep track of the current read buffer or reset it, every part of the code
700      * that reads sets the read buffer as desired.
701      */
702     if(!swapchain) {
703         /* Locking the primary render target which is not on a swapchain(=offscreen render target).
704          * Read from the back buffer
705          */
706         TRACE("Locking offscreen render target\n");
707         glReadBuffer(myDevice->offscreenBuffer);
708         srcIsUpsideDown = TRUE;
709     } else {
710         GLenum buffer = surface_get_gl_buffer((IWineD3DSurface *) This, (IWineD3DSwapChain *)swapchain);
711         TRACE("Locking %#x buffer\n", buffer);
712         glReadBuffer(buffer);
713         checkGLcall("glReadBuffer");
714
715         IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
716         srcIsUpsideDown = FALSE;
717     }
718
719     /* TODO: Get rid of the extra rectangle comparison and construction of a full surface rectangle */
720     if(!rect) {
721         local_rect.left = 0;
722         local_rect.top = 0;
723         local_rect.right = This->currentDesc.Width;
724         local_rect.bottom = This->currentDesc.Height;
725     } else {
726         local_rect = *rect;
727     }
728     /* TODO: Get rid of the extra GetPitch call, LockRect does that too. Cache the pitch */
729
730     switch(This->resource.format)
731     {
732         case WINED3DFMT_P8:
733         {
734             if(primary_render_target_is_p8(myDevice)) {
735                 /* In case of P8 render targets the index is stored in the alpha component */
736                 fmt = GL_ALPHA;
737                 type = GL_UNSIGNED_BYTE;
738                 mem = dest;
739                 bpp = This->bytesPerPixel;
740             } else {
741                 /* GL can't return palettized data, so read ARGB pixels into a
742                  * separate block of memory and convert them into palettized format
743                  * in software. Slow, but if the app means to use palettized render
744                  * targets and locks it...
745                  *
746                  * Use GL_RGB, GL_UNSIGNED_BYTE to read the surface for performance reasons
747                  * Don't use GL_BGR as in the WINED3DFMT_R8G8B8 case, instead watch out
748                  * for the color channels when palettizing the colors.
749                  */
750                 fmt = GL_RGB;
751                 type = GL_UNSIGNED_BYTE;
752                 pitch *= 3;
753                 mem = HeapAlloc(GetProcessHeap(), 0, This->resource.size * 3);
754                 if(!mem) {
755                     ERR("Out of memory\n");
756                     LEAVE_GL();
757                     return;
758                 }
759                 bpp = This->bytesPerPixel * 3;
760             }
761         }
762         break;
763
764         default:
765             mem = dest;
766             fmt = This->glDescription.glFormat;
767             type = This->glDescription.glType;
768             bpp = This->bytesPerPixel;
769     }
770
771     if(This->Flags & SFLAG_PBO) {
772         GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, This->pbo));
773         checkGLcall("glBindBufferARB");
774     }
775
776     glReadPixels(local_rect.left, local_rect.top,
777                  local_rect.right - local_rect.left,
778                  local_rect.bottom - local_rect.top,
779                  fmt, type, mem);
780     vcheckGLcall("glReadPixels");
781
782     if(This->Flags & SFLAG_PBO) {
783         GL_EXTCALL(glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0));
784         checkGLcall("glBindBufferARB");
785
786         /* Check if we need to flip the image. If we need to flip use glMapBufferARB
787          * to get a pointer to it and perform the flipping in software. This is a lot
788          * faster than calling glReadPixels for each line. In case we want more speed
789          * we should rerender it flipped in a FBO and read the data back from the FBO. */
790         if(!srcIsUpsideDown) {
791             GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
792             checkGLcall("glBindBufferARB");
793
794             mem = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_READ_WRITE_ARB));
795             checkGLcall("glMapBufferARB");
796         }
797     }
798
799     /* TODO: Merge this with the palettization loop below for P8 targets */
800     if(!srcIsUpsideDown) {
801         UINT len, off;
802         /* glReadPixels returns the image upside down, and there is no way to prevent this.
803             Flip the lines in software */
804         len = (local_rect.right - local_rect.left) * bpp;
805         off = local_rect.left * bpp;
806
807         row = HeapAlloc(GetProcessHeap(), 0, len);
808         if(!row) {
809             ERR("Out of memory\n");
810             if(This->resource.format == WINED3DFMT_P8) HeapFree(GetProcessHeap(), 0, mem);
811             LEAVE_GL();
812             return;
813         }
814
815         top = mem + pitch * local_rect.top;
816         bottom = mem + pitch * ( local_rect.bottom - local_rect.top - 1);
817         for(i = 0; i < (local_rect.bottom - local_rect.top) / 2; i++) {
818             memcpy(row, top + off, len);
819             memcpy(top + off, bottom + off, len);
820             memcpy(bottom + off, row, len);
821             top += pitch;
822             bottom -= pitch;
823         }
824         HeapFree(GetProcessHeap(), 0, row);
825
826         /* Unmap the temp PBO buffer */
827         if(This->Flags & SFLAG_PBO) {
828             GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB));
829             GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
830         }
831     }
832
833     LEAVE_GL();
834
835     /* For P8 textures we need to perform an inverse palette lookup. This is done by searching for a palette
836      * index which matches the RGB value. Note this isn't guaranteed to work when there are multiple entries for
837      * the same color but we have no choice.
838      * In case of P8 render targets, the index is stored in the alpha component so no conversion is needed.
839      */
840     if((This->resource.format == WINED3DFMT_P8) && !primary_render_target_is_p8(myDevice)) {
841         PALETTEENTRY *pal = NULL;
842         DWORD width = pitch / 3;
843         int x, y, c;
844
845         if(This->palette) {
846             pal = This->palette->palents;
847         } else {
848             ERR("Palette is missing, cannot perform inverse palette lookup\n");
849             HeapFree(GetProcessHeap(), 0, mem);
850             return ;
851         }
852
853         for(y = local_rect.top; y < local_rect.bottom; y++) {
854             for(x = local_rect.left; x < local_rect.right; x++) {
855                 /*                      start              lines            pixels      */
856                 BYTE *blue =  mem + y * pitch + x * (sizeof(BYTE) * 3);
857                 BYTE *green = blue  + 1;
858                 BYTE *red =   green + 1;
859
860                 for(c = 0; c < 256; c++) {
861                     if(*red   == pal[c].peRed   &&
862                        *green == pal[c].peGreen &&
863                        *blue  == pal[c].peBlue)
864                     {
865                         *((BYTE *) dest + y * width + x) = c;
866                         break;
867                     }
868                 }
869             }
870         }
871         HeapFree(GetProcessHeap(), 0, mem);
872     }
873 }
874
875 /* Read the framebuffer contents into a texture */
876 static void read_from_framebuffer_texture(IWineD3DSurfaceImpl *This)
877 {
878     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
879     IWineD3DSwapChainImpl *swapchain;
880     int bpp;
881     GLenum format, internal, type;
882     CONVERT_TYPES convert;
883     GLint prevRead;
884
885     d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp, This->srgb);
886
887     IWineD3DSurface_GetContainer((IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&swapchain);
888     /* Activate the surface to read from. In some situations it isn't the currently active target(e.g. backbuffer
889      * locking during offscreen rendering). RESOURCELOAD is ok because glCopyTexSubImage2D isn't affected by any
890      * states in the stateblock, and no driver was found yet that had bugs in that regard.
891      */
892     ActivateContext(device, (IWineD3DSurface *) This, CTXUSAGE_RESOURCELOAD);
893     surface_bind_and_dirtify(This);
894     ENTER_GL();
895
896     glGetIntegerv(GL_READ_BUFFER, &prevRead);
897
898     /* Select the correct read buffer, and give some debug output.
899      * There is no need to keep track of the current read buffer or reset it, every part of the code
900      * that reads sets the read buffer as desired.
901      */
902     if(!swapchain) {
903         /* Locking the primary render target which is not on a swapchain(=offscreen render target).
904          * Read from the back buffer
905          */
906         TRACE("Locking offscreen render target\n");
907         glReadBuffer(device->offscreenBuffer);
908     } else {
909         GLenum buffer = surface_get_gl_buffer((IWineD3DSurface *) This, (IWineD3DSwapChain *)swapchain);
910         TRACE("Locking %#x buffer\n", buffer);
911         glReadBuffer(buffer);
912         checkGLcall("glReadBuffer");
913
914         IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
915     }
916
917     if(!(This->Flags & SFLAG_ALLOCATED)) {
918         surface_allocate_surface(This, internal, This->pow2Width,
919                                  This->pow2Height, format, type);
920     }
921
922     clear_unused_channels(This);
923
924     /* If !SrcIsUpsideDown we should flip the surface.
925      * This can be done using glCopyTexSubImage2D but this
926      * is VERY slow, so don't do that. We should prevent
927      * this code from getting called in such cases or perhaps
928      * we can use FBOs */
929
930     glCopyTexSubImage2D(This->glDescription.target,
931                         This->glDescription.level,
932                         0, 0, 0, 0,
933                         This->currentDesc.Width,
934                         This->currentDesc.Height);
935     checkGLcall("glCopyTexSubImage2D");
936
937     glReadBuffer(prevRead);
938     vcheckGLcall("glReadBuffer");
939
940     LEAVE_GL();
941     TRACE("Updated target %d\n", This->glDescription.target);
942 }
943
944 static void surface_prepare_system_memory(IWineD3DSurfaceImpl *This) {
945     /* Performance optimization: Count how often a surface is locked, if it is locked regularly do not throw away the system memory copy.
946      * This avoids the need to download the surface from opengl all the time. The surface is still downloaded if the opengl texture is
947      * changed
948      */
949     if(!(This->Flags & SFLAG_DYNLOCK)) {
950         This->lockCount++;
951         /* MAXLOCKCOUNT is defined in wined3d_private.h */
952         if(This->lockCount > MAXLOCKCOUNT) {
953             TRACE("Surface is locked regularly, not freeing the system memory copy any more\n");
954             This->Flags |= SFLAG_DYNLOCK;
955         }
956     }
957
958     /* Create a PBO for dynamically locked surfaces but don't do it for converted or non-pow2 surfaces.
959      * Also don't create a PBO for systemmem surfaces.
960      */
961     if(GL_SUPPORT(ARB_PIXEL_BUFFER_OBJECT) && (This->Flags & SFLAG_DYNLOCK) && !(This->Flags & (SFLAG_PBO | SFLAG_CONVERTED | SFLAG_NONPOW2)) && (This->resource.pool != WINED3DPOOL_SYSTEMMEM)) {
962         GLenum error;
963         IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
964
965         ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
966         ENTER_GL();
967
968         GL_EXTCALL(glGenBuffersARB(1, &This->pbo));
969         error = glGetError();
970         if(This->pbo == 0 || error != GL_NO_ERROR) {
971             ERR("Failed to bind the PBO with error %s (%#x)\n", debug_glerror(error), error);
972         }
973
974         TRACE("Attaching pbo=%#x to (%p)\n", This->pbo, This);
975
976         GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
977         checkGLcall("glBindBufferARB");
978
979         GL_EXTCALL(glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->resource.size + 4, This->resource.allocatedMemory, GL_STREAM_DRAW_ARB));
980         checkGLcall("glBufferDataARB");
981
982         GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
983         checkGLcall("glBindBufferARB");
984
985         /* We don't need the system memory anymore and we can't even use it for PBOs */
986         if(!(This->Flags & SFLAG_CLIENT)) {
987             HeapFree(GetProcessHeap(), 0, This->resource.heapMemory);
988             This->resource.heapMemory = NULL;
989         }
990         This->resource.allocatedMemory = NULL;
991         This->Flags |= SFLAG_PBO;
992         LEAVE_GL();
993     } else if(!(This->resource.allocatedMemory || This->Flags & SFLAG_PBO)) {
994         /* Whatever surface we have, make sure that there is memory allocated for the downloaded copy,
995          * or a pbo to map
996          */
997         if(!This->resource.heapMemory) {
998             This->resource.heapMemory = HeapAlloc(GetProcessHeap() ,0 , This->resource.size + RESOURCE_ALIGNMENT);
999         }
1000         This->resource.allocatedMemory =
1001                 (BYTE *)(((ULONG_PTR) This->resource.heapMemory + (RESOURCE_ALIGNMENT - 1)) & ~(RESOURCE_ALIGNMENT - 1));
1002         if(This->Flags & SFLAG_INSYSMEM) {
1003             ERR("Surface without memory or pbo has SFLAG_INSYSMEM set!\n");
1004         }
1005     }
1006 }
1007
1008 static HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKED_RECT* pLockedRect, CONST RECT* pRect, DWORD Flags) {
1009     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1010     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
1011     IWineD3DSwapChain *swapchain = NULL;
1012
1013     TRACE("(%p) : rect@%p flags(%08x), output lockedRect@%p, memory@%p\n", This, pRect, Flags, pLockedRect, This->resource.allocatedMemory);
1014
1015     /* This is also done in the base class, but we have to verify this before loading any data from
1016      * gl into the sysmem copy. The PBO may be mapped, a different rectangle locked, the discard flag
1017      * may interfere, and all other bad things may happen
1018      */
1019     if (This->Flags & SFLAG_LOCKED) {
1020         WARN("Surface is already locked, returning D3DERR_INVALIDCALL\n");
1021         return WINED3DERR_INVALIDCALL;
1022     }
1023     This->Flags |= SFLAG_LOCKED;
1024
1025     if (!(This->Flags & SFLAG_LOCKABLE))
1026     {
1027         TRACE("Warning: trying to lock unlockable surf@%p\n", This);
1028     }
1029
1030     if (Flags & WINED3DLOCK_DISCARD) {
1031         /* Set SFLAG_INSYSMEM, so we'll never try to download the data from the texture. */
1032         TRACE("WINED3DLOCK_DISCARD flag passed, marking local copy as up to date\n");
1033         surface_prepare_system_memory(This); /* Makes sure memory is allocated */
1034         This->Flags |= SFLAG_INSYSMEM;
1035         goto lock_end;
1036     }
1037
1038     if (This->Flags & SFLAG_INSYSMEM) {
1039         TRACE("Local copy is up to date, not downloading data\n");
1040         surface_prepare_system_memory(This); /* Makes sure memory is allocated */
1041         goto lock_end;
1042     }
1043
1044     /* Now download the surface content from opengl
1045      * Use the render target readback if the surface is on a swapchain(=onscreen render target) or the current primary target
1046      * Offscreen targets which are not active at the moment or are higher targets(FBOs) can be locked with the texture path
1047      */
1048     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
1049     if(swapchain || iface == myDevice->render_targets[0]) {
1050         const RECT *pass_rect = pRect;
1051
1052         /* IWineD3DSurface_LoadLocation does not check if the rectangle specifies the full surfaces
1053          * because most caller functions do not need that. So do that here
1054          */
1055         if(pRect &&
1056            pRect->top    == 0 &&
1057            pRect->left   == 0 &&
1058            pRect->right  == This->currentDesc.Width &&
1059            pRect->bottom == This->currentDesc.Height) {
1060             pass_rect = NULL;
1061         }
1062
1063         switch(wined3d_settings.rendertargetlock_mode) {
1064             case RTL_TEXDRAW:
1065             case RTL_TEXTEX:
1066                 FIXME("Reading from render target with a texture isn't implemented yet, falling back to framebuffer reading\n");
1067 #if 0
1068                 /* Disabled for now. LoadLocation prefers the texture over the drawable as the source. So if we copy to the
1069                  * texture first, then to sysmem, we'll avoid glReadPixels and use glCopyTexImage and glGetTexImage2D instead.
1070                  * This may be faster on some cards
1071                  */
1072                 IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL /* No partial texture copy yet */);
1073 #endif
1074                 /* drop through */
1075
1076             case RTL_AUTO:
1077             case RTL_READDRAW:
1078             case RTL_READTEX:
1079                 IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, pRect);
1080                 break;
1081
1082             case RTL_DISABLE:
1083                 break;
1084         }
1085         if(swapchain) IWineD3DSwapChain_Release(swapchain);
1086
1087     } else if(iface == myDevice->stencilBufferTarget) {
1088         /** the depth stencil in openGL has a format of GL_FLOAT
1089          * which should be good for WINED3DFMT_D16_LOCKABLE
1090          * and WINED3DFMT_D16
1091          * it is unclear what format the stencil buffer is in except.
1092          * 'Each index is converted to fixed point...
1093          * If GL_MAP_STENCIL is GL_TRUE, indices are replaced by their
1094          * mappings in the table GL_PIXEL_MAP_S_TO_S.
1095          * glReadPixels(This->lockedRect.left,
1096          *             This->lockedRect.bottom - j - 1,
1097          *             This->lockedRect.right - This->lockedRect.left,
1098          *             1,
1099          *             GL_DEPTH_COMPONENT,
1100          *             type,
1101          *             (char *)pLockedRect->pBits + (pLockedRect->Pitch * (j-This->lockedRect.top)));
1102          *
1103          * Depth Stencil surfaces which are not the current depth stencil target should have their data in a
1104          * gl texture(next path), or in local memory(early return because of set SFLAG_INSYSMEM above). If
1105          * none of that is the case the problem is not in this function :-)
1106          ********************************************/
1107         FIXME("Depth stencil locking not supported yet\n");
1108     } else {
1109         /* This path is for normal surfaces, offscreen render targets and everything else that is in a gl texture */
1110         TRACE("locking an ordinary surface\n");
1111         IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL /* no partial locking for textures yet */);
1112     }
1113
1114 lock_end:
1115     if(This->Flags & SFLAG_PBO) {
1116         ActivateContext(myDevice, myDevice->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
1117         ENTER_GL();
1118         GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
1119         checkGLcall("glBindBufferARB");
1120
1121         /* This shouldn't happen but could occur if some other function didn't handle the PBO properly */
1122         if(This->resource.allocatedMemory) {
1123             ERR("The surface already has PBO memory allocated!\n");
1124         }
1125
1126         This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_READ_WRITE_ARB));
1127         checkGLcall("glMapBufferARB");
1128
1129         /* Make sure the pbo isn't set anymore in order not to break non-pbo calls */
1130         GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
1131         checkGLcall("glBindBufferARB");
1132
1133         LEAVE_GL();
1134     }
1135
1136     if (Flags & (WINED3DLOCK_NO_DIRTY_UPDATE | WINED3DLOCK_READONLY)) {
1137         /* Don't dirtify */
1138     } else {
1139         IWineD3DBaseTexture *pBaseTexture;
1140         /**
1141          * Dirtify on lock
1142          * as seen in msdn docs
1143          */
1144         IWineD3DSurface_AddDirtyRect(iface, pRect);
1145
1146         /** Dirtify Container if needed */
1147         if (WINED3D_OK == IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&pBaseTexture) && pBaseTexture != NULL) {
1148             TRACE("Making container dirty\n");
1149             IWineD3DBaseTexture_SetDirty(pBaseTexture, TRUE);
1150             IWineD3DBaseTexture_Release(pBaseTexture);
1151         } else {
1152             TRACE("Surface is standalone, no need to dirty the container\n");
1153         }
1154     }
1155
1156     return IWineD3DBaseSurfaceImpl_LockRect(iface, pLockedRect, pRect, Flags);
1157 }
1158
1159 static void flush_to_framebuffer_drawpixels(IWineD3DSurfaceImpl *This, GLenum fmt, GLenum type, UINT bpp, const BYTE *mem) {
1160     GLint  prev_store;
1161     GLint  prev_rasterpos[4];
1162     GLint skipBytes = 0;
1163     UINT pitch = IWineD3DSurface_GetPitch((IWineD3DSurface *) This);    /* target is argb, 4 byte */
1164     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
1165     IWineD3DSwapChainImpl *swapchain;
1166
1167     /* Activate the correct context for the render target */
1168     ActivateContext(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT);
1169     ENTER_GL();
1170
1171     IWineD3DSurface_GetContainer((IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&swapchain);
1172     if(!swapchain) {
1173         /* Primary offscreen render target */
1174         TRACE("Offscreen render target\n");
1175         glDrawBuffer(myDevice->offscreenBuffer);
1176         checkGLcall("glDrawBuffer(myDevice->offscreenBuffer)");
1177     } else {
1178         GLenum buffer = surface_get_gl_buffer((IWineD3DSurface *) This, (IWineD3DSwapChain *)swapchain);
1179         TRACE("Unlocking %#x buffer\n", buffer);
1180         glDrawBuffer(buffer);
1181         checkGLcall("glDrawBuffer");
1182
1183         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
1184     }
1185
1186     glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1187     vcheckGLcall("glIntegerv");
1188     glGetIntegerv(GL_CURRENT_RASTER_POSITION, &prev_rasterpos[0]);
1189     vcheckGLcall("glIntegerv");
1190     glPixelZoom(1.0, -1.0);
1191     vcheckGLcall("glPixelZoom");
1192
1193     /* If not fullscreen, we need to skip a number of bytes to find the next row of data */
1194     glGetIntegerv(GL_UNPACK_ROW_LENGTH, &skipBytes);
1195     glPixelStorei(GL_UNPACK_ROW_LENGTH, This->currentDesc.Width);
1196
1197     glRasterPos3i(This->lockedRect.left, This->lockedRect.top, 1);
1198     vcheckGLcall("glRasterPos2f");
1199
1200     /* Some drivers(radeon dri, others?) don't like exceptions during
1201      * glDrawPixels. If the surface is a DIB section, it might be in GDIMode
1202      * after ReleaseDC. Reading it will cause an exception, which x11drv will
1203      * catch to put the dib section in InSync mode, which leads to a crash
1204      * and a blocked x server on my radeon card.
1205      *
1206      * The following lines read the dib section so it is put in InSync mode
1207      * before glDrawPixels is called and the crash is prevented. There won't
1208      * be any interfering gdi accesses, because UnlockRect is called from
1209      * ReleaseDC, and the app won't use the dc any more afterwards.
1210      */
1211     if((This->Flags & SFLAG_DIBSECTION) && !(This->Flags & SFLAG_PBO)) {
1212         volatile BYTE read;
1213         read = This->resource.allocatedMemory[0];
1214     }
1215
1216     if(This->Flags & SFLAG_PBO) {
1217         GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
1218         checkGLcall("glBindBufferARB");
1219     }
1220
1221     /* When the surface is locked we only have to refresh the locked part else we need to update the whole image */
1222     if(This->Flags & SFLAG_LOCKED) {
1223         glDrawPixels(This->lockedRect.right - This->lockedRect.left,
1224                      (This->lockedRect.bottom - This->lockedRect.top)-1,
1225                      fmt, type,
1226                      mem + bpp * This->lockedRect.left + pitch * This->lockedRect.top);
1227         checkGLcall("glDrawPixels");
1228     } else {
1229         glDrawPixels(This->currentDesc.Width,
1230                      This->currentDesc.Height,
1231                      fmt, type, mem);
1232         checkGLcall("glDrawPixels");
1233     }
1234
1235     if(This->Flags & SFLAG_PBO) {
1236         GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
1237         checkGLcall("glBindBufferARB");
1238     }
1239
1240     glPixelZoom(1.0,1.0);
1241     vcheckGLcall("glPixelZoom");
1242
1243     glRasterPos3iv(&prev_rasterpos[0]);
1244     vcheckGLcall("glRasterPos3iv");
1245
1246     /* Reset to previous pack row length */
1247     glPixelStorei(GL_UNPACK_ROW_LENGTH, skipBytes);
1248     vcheckGLcall("glPixelStorei GL_UNPACK_ROW_LENGTH");
1249
1250     if(!swapchain) {
1251         glDrawBuffer(myDevice->offscreenBuffer);
1252         checkGLcall("glDrawBuffer(myDevice->offscreenBuffer)");
1253     } else if(swapchain->backBuffer) {
1254         glDrawBuffer(GL_BACK);
1255         checkGLcall("glDrawBuffer(GL_BACK)");
1256     } else {
1257         glDrawBuffer(GL_FRONT);
1258         checkGLcall("glDrawBuffer(GL_FRONT)");
1259     }
1260     LEAVE_GL();
1261
1262     return;
1263 }
1264
1265 static HRESULT WINAPI IWineD3DSurfaceImpl_UnlockRect(IWineD3DSurface *iface) {
1266     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1267     IWineD3DDeviceImpl  *myDevice = This->resource.wineD3DDevice;
1268     IWineD3DSwapChainImpl *swapchain = NULL;
1269     BOOL fullsurface;
1270
1271     if (!(This->Flags & SFLAG_LOCKED)) {
1272         WARN("trying to Unlock an unlocked surf@%p\n", This);
1273         return WINED3DERR_INVALIDCALL;
1274     }
1275
1276     if (This->Flags & SFLAG_PBO) {
1277         TRACE("Freeing PBO memory\n");
1278         ActivateContext(myDevice, myDevice->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
1279         ENTER_GL();
1280         GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, This->pbo));
1281         GL_EXTCALL(glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB));
1282         GL_EXTCALL(glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0));
1283         checkGLcall("glUnmapBufferARB");
1284         LEAVE_GL();
1285         This->resource.allocatedMemory = NULL;
1286     }
1287
1288     TRACE("(%p) : dirtyfied(%d)\n", This, This->Flags & (SFLAG_INDRAWABLE | SFLAG_INTEXTURE) ? 0 : 1);
1289
1290     if (This->Flags & (SFLAG_INDRAWABLE | SFLAG_INTEXTURE)) {
1291         TRACE("(%p) : Not Dirtified so nothing to do, return now\n", This);
1292         goto unlock_end;
1293     }
1294
1295     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain);
1296     if(swapchain || (myDevice->render_targets && iface == myDevice->render_targets[0])) {
1297         if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
1298
1299         if(wined3d_settings.rendertargetlock_mode == RTL_DISABLE) {
1300             static BOOL warned = FALSE;
1301             if(!warned) {
1302                 ERR("The application tries to write to the render target, but render target locking is disabled\n");
1303                 warned = TRUE;
1304             }
1305             goto unlock_end;
1306         }
1307
1308         if(This->dirtyRect.left   == 0 &&
1309            This->dirtyRect.top    == 0 &&
1310            This->dirtyRect.right  == This->currentDesc.Width &&
1311            This->dirtyRect.bottom == This->currentDesc.Height) {
1312             fullsurface = TRUE;
1313         } else {
1314             /* TODO: Proper partial rectangle tracking */
1315             fullsurface = FALSE;
1316             This->Flags |= SFLAG_INSYSMEM;
1317         }
1318
1319         switch(wined3d_settings.rendertargetlock_mode) {
1320             case RTL_READTEX:
1321             case RTL_TEXTEX:
1322                 ActivateContext(myDevice, iface, CTXUSAGE_BLIT);
1323                 IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL /* partial texture loading not supported yet */);
1324                 /* drop through */
1325
1326             case RTL_AUTO:
1327             case RTL_READDRAW:
1328             case RTL_TEXDRAW:
1329                 IWineD3DSurface_LoadLocation(iface, SFLAG_INDRAWABLE, fullsurface ? NULL : &This->dirtyRect);
1330                 break;
1331         }
1332
1333         if(!fullsurface) {
1334             /* Partial rectangle tracking is not commonly implemented, it is only done for render targets. Overwrite
1335              * the flags to bring them back into a sane state. INSYSMEM was set before to tell LoadLocation where
1336              * to read the rectangle from. Indrawable is set because all modifications from the partial sysmem copy
1337              * are written back to the drawable, thus the surface is merged again in the drawable. The sysmem copy is
1338              * not fully up to date because only a subrectangle was read in LockRect.
1339              */
1340             This->Flags &= ~SFLAG_INSYSMEM;
1341             This->Flags |= SFLAG_INDRAWABLE;
1342         }
1343
1344         This->dirtyRect.left   = This->currentDesc.Width;
1345         This->dirtyRect.top    = This->currentDesc.Height;
1346         This->dirtyRect.right  = 0;
1347         This->dirtyRect.bottom = 0;
1348     } else if(iface == myDevice->stencilBufferTarget) {
1349         FIXME("Depth Stencil buffer locking is not implemented\n");
1350     } else {
1351         /* The rest should be a normal texture */
1352         IWineD3DBaseTextureImpl *impl;
1353         /* Check if the texture is bound, if yes dirtify the sampler to force a re-upload of the texture
1354          * Can't load the texture here because PreLoad may destroy and recreate the gl texture, so sampler
1355          * states need resetting
1356          */
1357         if(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&impl) == WINED3D_OK) {
1358             if(impl->baseTexture.bindCount) {
1359                 IWineD3DDeviceImpl_MarkStateDirty(myDevice, STATE_SAMPLER(impl->baseTexture.sampler));
1360             }
1361             IWineD3DBaseTexture_Release((IWineD3DBaseTexture *) impl);
1362         }
1363     }
1364
1365     unlock_end:
1366     This->Flags &= ~SFLAG_LOCKED;
1367     memset(&This->lockedRect, 0, sizeof(RECT));
1368
1369     /* Overlays have to be redrawn manually after changes with the GL implementation */
1370     if(This->overlay_dest) {
1371         IWineD3DSurface_DrawOverlay(iface);
1372     }
1373     return WINED3D_OK;
1374 }
1375
1376 HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
1377     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1378     WINED3DLOCKED_RECT lock;
1379     HRESULT hr;
1380     RGBQUAD col[256];
1381
1382     TRACE("(%p)->(%p)\n",This,pHDC);
1383
1384     if(This->Flags & SFLAG_USERPTR) {
1385         ERR("Not supported on surfaces with an application-provided surfaces\n");
1386         return WINEDDERR_NODC;
1387     }
1388
1389     /* Give more detailed info for ddraw */
1390     if (This->Flags & SFLAG_DCINUSE)
1391         return WINEDDERR_DCALREADYCREATED;
1392
1393     /* Can't GetDC if the surface is locked */
1394     if (This->Flags & SFLAG_LOCKED)
1395         return WINED3DERR_INVALIDCALL;
1396
1397     /* According to Direct3D9 docs, only these formats are supported */
1398     if (((IWineD3DImpl *)This->resource.wineD3DDevice->wineD3D)->dxVersion > 7) {
1399         if (This->resource.format != WINED3DFMT_R5G6B5 &&
1400             This->resource.format != WINED3DFMT_X1R5G5B5 &&
1401             This->resource.format != WINED3DFMT_R8G8B8 &&
1402             This->resource.format != WINED3DFMT_X8R8G8B8) return WINED3DERR_INVALIDCALL;
1403     }
1404
1405     memset(&lock, 0, sizeof(lock)); /* To be sure */
1406
1407     /* Create a DIB section if there isn't a hdc yet */
1408     if(!This->hDC) {
1409         IWineD3DBaseSurfaceImpl_CreateDIBSection(iface);
1410         if(This->Flags & SFLAG_CLIENT) {
1411             IWineD3DSurface_PreLoad(iface);
1412         }
1413
1414         /* Use the dib section from now on if we are not using a PBO */
1415         if(!(This->Flags & SFLAG_PBO))
1416             This->resource.allocatedMemory = This->dib.bitmap_data;
1417     }
1418
1419     /* Lock the surface */
1420     hr = IWineD3DSurface_LockRect(iface,
1421                                   &lock,
1422                                   NULL,
1423                                   0);
1424
1425     if(This->Flags & SFLAG_PBO) {
1426         /* Sync the DIB with the PBO. This can't be done earlier because LockRect activates the allocatedMemory */
1427         memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, This->dib.bitmap_size);
1428     }
1429
1430     if(FAILED(hr)) {
1431         ERR("IWineD3DSurface_LockRect failed with hr = %08x\n", hr);
1432         /* keep the dib section */
1433         return hr;
1434     }
1435
1436     if(This->resource.format == WINED3DFMT_P8 ||
1437         This->resource.format == WINED3DFMT_A8P8) {
1438         /* GetDC on palettized formats is unsupported in D3D9, and the method is missing in
1439             D3D8, so this should only be used for DX <=7 surfaces (with non-device palettes) */
1440         unsigned int n;
1441         PALETTEENTRY *pal = NULL;
1442
1443         if(This->palette) {
1444             pal = This->palette->palents;
1445         } else {
1446             IWineD3DSurfaceImpl *dds_primary;
1447             IWineD3DSwapChainImpl *swapchain;
1448             swapchain = (IWineD3DSwapChainImpl *)This->resource.wineD3DDevice->swapchains[0];
1449             dds_primary = (IWineD3DSurfaceImpl *)swapchain->frontBuffer;
1450             if (dds_primary && dds_primary->palette)
1451                 pal = dds_primary->palette->palents;
1452         }
1453
1454         if (pal) {
1455             for (n=0; n<256; n++) {
1456                 col[n].rgbRed   = pal[n].peRed;
1457                 col[n].rgbGreen = pal[n].peGreen;
1458                 col[n].rgbBlue  = pal[n].peBlue;
1459                 col[n].rgbReserved = 0;
1460             }
1461             SetDIBColorTable(This->hDC, 0, 256, col);
1462         }
1463     }
1464
1465     *pHDC = This->hDC;
1466     TRACE("returning %p\n",*pHDC);
1467     This->Flags |= SFLAG_DCINUSE;
1468
1469     return WINED3D_OK;
1470 }
1471
1472 HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) {
1473     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
1474
1475     TRACE("(%p)->(%p)\n",This,hDC);
1476
1477     if (!(This->Flags & SFLAG_DCINUSE))
1478         return WINED3DERR_INVALIDCALL;
1479
1480     if (This->hDC !=hDC) {
1481         WARN("Application tries to release an invalid DC(%p), surface dc is %p\n", hDC, This->hDC);
1482         return WINED3DERR_INVALIDCALL;
1483     }
1484
1485     if((This->Flags & SFLAG_PBO) && This->resource.allocatedMemory) {
1486         /* Copy the contents of the DIB over to the PBO */
1487         memcpy(This->resource.allocatedMemory, This->dib.bitmap_data, This->dib.bitmap_size);
1488     }
1489
1490     /* we locked first, so unlock now */
1491     IWineD3DSurface_UnlockRect(iface);
1492
1493     This->Flags &= ~SFLAG_DCINUSE;
1494
1495     return WINED3D_OK;
1496 }
1497
1498 /* ******************************************************
1499    IWineD3DSurface Internal (No mapping to directx api) parts follow
1500    ****************************************************** */
1501
1502 HRESULT d3dfmt_get_conv(IWineD3DSurfaceImpl *This, BOOL need_alpha_ck, BOOL use_texturing, GLenum *format, GLenum *internal, GLenum *type, CONVERT_TYPES *convert, int *target_bpp, BOOL srgb_mode) {
1503     BOOL colorkey_active = need_alpha_ck && (This->CKeyFlags & WINEDDSD_CKSRCBLT);
1504     const GlPixelFormatDesc *glDesc;
1505     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
1506     getFormatDescEntry(This->resource.format, &GLINFO_LOCATION, &glDesc);
1507
1508     /* Default values: From the surface */
1509     *format = glDesc->glFormat;
1510     *type = glDesc->glType;
1511     *convert = NO_CONVERSION;
1512     *target_bpp = This->bytesPerPixel;
1513
1514     if(srgb_mode) {
1515         *internal = glDesc->glGammaInternal;
1516     } else if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
1517         *internal = glDesc->rtInternal;
1518     } else {
1519         *internal = glDesc->glInternal;
1520     }
1521
1522     /* Ok, now look if we have to do any conversion */
1523     switch(This->resource.format) {
1524         case WINED3DFMT_P8:
1525             /* ****************
1526                 Paletted Texture
1527                 **************** */
1528
1529              /* Use conversion when the paletted texture extension OR fragment shaders are available. When either
1530              * of the two is available make sure texturing is requested as neither of the two works in
1531              * conjunction with calls like glDraw-/glReadPixels. Further also use conversion in case of color keying.
1532              * Paletted textures can be emulated using shaders but only do that for 2D purposes e.g. situations
1533              * in which the main render target uses p8. Some games like GTA Vice City use P8 for texturing which
1534              * conflicts with this.
1535              */
1536             if( !(GL_SUPPORT(EXT_PALETTED_TEXTURE) || (GL_SUPPORT(ARB_FRAGMENT_PROGRAM) && primary_render_target_is_p8(device))) || colorkey_active || !use_texturing ) {
1537                 *format = GL_RGBA;
1538                 *internal = GL_RGBA;
1539                 *type = GL_UNSIGNED_BYTE;
1540                 *target_bpp = 4;
1541                 if(colorkey_active) {
1542                     *convert = CONVERT_PALETTED_CK;
1543                 } else {
1544                     *convert = CONVERT_PALETTED;
1545                 }
1546             }
1547             else if(!GL_SUPPORT(EXT_PALETTED_TEXTURE) && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) {
1548                 *format = GL_ALPHA;
1549                 *internal = GL_RGBA;
1550                 *type = GL_UNSIGNED_BYTE;
1551                 *target_bpp = 1;
1552             }
1553
1554             break;
1555
1556         case WINED3DFMT_R3G3B2:
1557             /* **********************
1558                 GL_UNSIGNED_BYTE_3_3_2
1559                 ********************** */
1560             if (colorkey_active) {
1561                 /* This texture format will never be used.. So do not care about color keying
1562                     up until the point in time it will be needed :-) */
1563                 FIXME(" ColorKeying not supported in the RGB 332 format !\n");
1564             }
1565             break;
1566
1567         case WINED3DFMT_R5G6B5:
1568             if (colorkey_active) {
1569                 *convert = CONVERT_CK_565;
1570                 *format = GL_RGBA;
1571                 *internal = GL_RGBA;
1572                 *type = GL_UNSIGNED_SHORT_5_5_5_1;
1573             }
1574             break;
1575
1576         case WINED3DFMT_X1R5G5B5:
1577             if (colorkey_active) {
1578                 *convert = CONVERT_CK_5551;
1579                 *format = GL_BGRA;
1580                 *internal = GL_RGBA;
1581                 *type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
1582             }
1583             break;
1584
1585         case WINED3DFMT_R8G8B8:
1586             if (colorkey_active) {
1587                 *convert = CONVERT_CK_RGB24;
1588                 *format = GL_RGBA;
1589                 *internal = GL_RGBA;
1590                 *type = GL_UNSIGNED_INT_8_8_8_8;
1591                 *target_bpp = 4;
1592             }
1593             break;
1594
1595         case WINED3DFMT_X8R8G8B8:
1596             if (colorkey_active) {
1597                 *convert = CONVERT_RGB32_888;
1598                 *format = GL_RGBA;
1599                 *internal = GL_RGBA;
1600                 *type = GL_UNSIGNED_INT_8_8_8_8;
1601             }
1602             break;
1603
1604         case WINED3DFMT_V8U8:
1605             if(GL_SUPPORT(NV_TEXTURE_SHADER3)) break;
1606             else if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
1607                 *format = GL_DUDV_ATI;
1608                 *internal = GL_DU8DV8_ATI;
1609                 *type = GL_BYTE;
1610                 /* No conversion - Just change the gl type */
1611                 break;
1612             }
1613             *convert = CONVERT_V8U8;
1614             *format = GL_BGR;
1615             *internal = GL_RGB8;
1616             *type = GL_UNSIGNED_BYTE;
1617             *target_bpp = 3;
1618             break;
1619
1620         case WINED3DFMT_L6V5U5:
1621             *convert = CONVERT_L6V5U5;
1622             if(GL_SUPPORT(NV_TEXTURE_SHADER)) {
1623                 *target_bpp = 3;
1624                 /* Use format and types from table */
1625             } else {
1626                 /* Load it into unsigned R5G6B5, swap L and V channels, and revert that in the shader */
1627                 *target_bpp = 2;
1628                 *format = GL_RGB;
1629                 *internal = GL_RGB5;
1630                 *type = GL_UNSIGNED_SHORT_5_6_5;
1631             }
1632             break;
1633
1634         case WINED3DFMT_X8L8V8U8:
1635             *convert = CONVERT_X8L8V8U8;
1636             *target_bpp = 4;
1637             if(GL_SUPPORT(NV_TEXTURE_SHADER)) {
1638                 /* Use formats from gl table. It is a bit unfortunate, but the conversion
1639                  * is needed to set the X format to 255 to get 1.0 for alpha when sampling
1640                  * the texture. OpenGL can't use GL_DSDT8_MAG8_NV as internal format with
1641                  * the needed type and format parameter, so the internal format contains a
1642                  * 4th component, which is returned as alpha
1643                  */
1644             } else {
1645                 /* Not supported by GL_ATI_envmap_bumpmap */
1646                 *format = GL_BGRA;
1647                 *internal = GL_RGB8;
1648                 *type = GL_UNSIGNED_INT_8_8_8_8_REV;
1649             }
1650             break;
1651
1652         case WINED3DFMT_Q8W8V8U8:
1653             if(GL_SUPPORT(NV_TEXTURE_SHADER3)) break;
1654             *convert = CONVERT_Q8W8V8U8;
1655             *format = GL_BGRA;
1656             *internal = GL_RGBA8;
1657             *type = GL_UNSIGNED_BYTE;
1658             *target_bpp = 4;
1659             /* Not supported by GL_ATI_envmap_bumpmap */
1660             break;
1661
1662         case WINED3DFMT_V16U16:
1663             if(GL_SUPPORT(NV_TEXTURE_SHADER3)) break;
1664             *convert = CONVERT_V16U16;
1665             *format = GL_BGR;
1666             *internal = GL_RGB16_EXT;
1667             *type = GL_UNSIGNED_SHORT;
1668             *target_bpp = 6;
1669             /* What should I do here about GL_ATI_envmap_bumpmap?
1670              * Convert it or allow data loss by loading it into a 8 bit / channel texture?
1671              */
1672             break;
1673
1674         case WINED3DFMT_A4L4:
1675             /* A4L4 exists as an internal gl format, but for some reason there is not
1676              * format+type combination to load it. Thus convert it to A8L8, then load it
1677              * with A4L4 internal, but A8L8 format+type
1678              */
1679             *convert = CONVERT_A4L4;
1680             *format = GL_LUMINANCE_ALPHA;
1681             *internal = GL_LUMINANCE4_ALPHA4;
1682             *type = GL_UNSIGNED_BYTE;
1683             *target_bpp = 2;
1684             break;
1685
1686         case WINED3DFMT_R32F:
1687             /* Can be loaded in theory with fmt=GL_RED, type=GL_FLOAT, but this fails. The reason
1688              * is that D3D expects the undefined green, blue and alpha channels to return 1.0
1689              * when sampling, but OpenGL sets green and blue to 0.0 instead. Thus we have to inject
1690              * 1.0 instead.
1691              *
1692              * The alpha channel defaults to 1.0 in opengl, so nothing has to be done about it.
1693              */
1694             *convert = CONVERT_R32F;
1695             *format = GL_RGB;
1696             *internal = GL_RGB32F_ARB;
1697             *type = GL_FLOAT;
1698             *target_bpp = 12;
1699             break;
1700
1701         case WINED3DFMT_R16F:
1702             /* Similar to R32F */
1703             *convert = CONVERT_R16F;
1704             *format = GL_RGB;
1705             *internal = GL_RGB16F_ARB;
1706             *type = GL_HALF_FLOAT_ARB;
1707             *target_bpp = 6;
1708             break;
1709
1710         case WINED3DFMT_G16R16:
1711             *convert = CONVERT_G16R16;
1712             *format = GL_RGB;
1713             *internal = GL_RGB16_EXT;
1714             *type = GL_UNSIGNED_SHORT;
1715             *target_bpp = 6;
1716             break;
1717
1718         default:
1719             break;
1720     }
1721
1722     return WINED3D_OK;
1723 }
1724
1725 HRESULT d3dfmt_convert_surface(BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height, UINT outpitch, CONVERT_TYPES convert, IWineD3DSurfaceImpl *This) {
1726     BYTE *source, *dest;
1727     TRACE("(%p)->(%p),(%d,%d,%d,%d,%p)\n", src, dst, pitch, height, outpitch, convert,This);
1728
1729     switch (convert) {
1730         case NO_CONVERSION:
1731         {
1732             memcpy(dst, src, pitch * height);
1733             break;
1734         }
1735         case CONVERT_PALETTED:
1736         case CONVERT_PALETTED_CK:
1737         {
1738             IWineD3DPaletteImpl* pal = This->palette;
1739             BYTE table[256][4];
1740             unsigned int x, y;
1741
1742             if( pal == NULL) {
1743                 /* TODO: If we are a sublevel, try to get the palette from level 0 */
1744             }
1745
1746             d3dfmt_p8_init_palette(This, table, (convert == CONVERT_PALETTED_CK));
1747
1748             for (y = 0; y < height; y++)
1749             {
1750                 source = src + pitch * y;
1751                 dest = dst + outpitch * y;
1752                 /* This is an 1 bpp format, using the width here is fine */
1753                 for (x = 0; x < width; x++) {
1754                     BYTE color = *source++;
1755                     *dest++ = table[color][0];
1756                     *dest++ = table[color][1];
1757                     *dest++ = table[color][2];
1758                     *dest++ = table[color][3];
1759                 }
1760             }
1761         }
1762         break;
1763
1764         case CONVERT_CK_565:
1765         {
1766             /* Converting the 565 format in 5551 packed to emulate color-keying.
1767
1768               Note : in all these conversion, it would be best to average the averaging
1769                       pixels to get the color of the pixel that will be color-keyed to
1770                       prevent 'color bleeding'. This will be done later on if ever it is
1771                       too visible.
1772
1773               Note2: Nvidia documents say that their driver does not support alpha + color keying
1774                      on the same surface and disables color keying in such a case
1775             */
1776             unsigned int x, y;
1777             WORD *Source;
1778             WORD *Dest;
1779
1780             TRACE("Color keyed 565\n");
1781
1782             for (y = 0; y < height; y++) {
1783                 Source = (WORD *) (src + y * pitch);
1784                 Dest = (WORD *) (dst + y * outpitch);
1785                 for (x = 0; x < width; x++ ) {
1786                     WORD color = *Source++;
1787                     *Dest = ((color & 0xFFC0) | ((color & 0x1F) << 1));
1788                     if ((color < This->SrcBltCKey.dwColorSpaceLowValue) ||
1789                         (color > This->SrcBltCKey.dwColorSpaceHighValue)) {
1790                         *Dest |= 0x0001;
1791                     }
1792                     Dest++;
1793                 }
1794             }
1795         }
1796         break;
1797
1798         case CONVERT_CK_5551:
1799         {
1800             /* Converting X1R5G5B5 format to R5G5B5A1 to emulate color-keying. */
1801             unsigned int x, y;
1802             WORD *Source;
1803             WORD *Dest;
1804             TRACE("Color keyed 5551\n");
1805             for (y = 0; y < height; y++) {
1806                 Source = (WORD *) (src + y * pitch);
1807                 Dest = (WORD *) (dst + y * outpitch);
1808                 for (x = 0; x < width; x++ ) {
1809                     WORD color = *Source++;
1810                     *Dest = color;
1811                     if ((color < This->SrcBltCKey.dwColorSpaceLowValue) ||
1812                         (color > This->SrcBltCKey.dwColorSpaceHighValue)) {
1813                         *Dest |= (1 << 15);
1814                     }
1815                     else {
1816                         *Dest &= ~(1 << 15);
1817                     }
1818                     Dest++;
1819                 }
1820             }
1821         }
1822         break;
1823
1824         case CONVERT_RGB32_888:
1825         {
1826             /* Converting X8R8G8B8 format to R8G8B8A8 with color-keying. */
1827             unsigned int x, y;
1828             for (y = 0; y < height; y++)
1829             {
1830                 source = src + pitch * y;
1831                 dest = dst + outpitch * y;
1832                 for (x = 0; x < width; x++) {
1833                     DWORD color = 0xffffff & *(DWORD*)source;
1834                     DWORD dstcolor = color << 8;
1835                     if ((color < This->SrcBltCKey.dwColorSpaceLowValue) ||
1836                         (color > This->SrcBltCKey.dwColorSpaceHighValue)) {
1837                         dstcolor |= 0xff;
1838                     }
1839                     *(DWORD*)dest = dstcolor;
1840                     source += 4;
1841                     dest += 4;
1842                 }
1843             }
1844         }
1845         break;
1846
1847         case CONVERT_V8U8:
1848         {
1849             unsigned int x, y;
1850             short *Source;
1851             unsigned char *Dest;
1852             for(y = 0; y < height; y++) {
1853                 Source = (short *) (src + y * pitch);
1854                 Dest = dst + y * outpitch;
1855                 for (x = 0; x < width; x++ ) {
1856                     long color = (*Source++);
1857                     /* B */ Dest[0] = 0xff;
1858                     /* G */ Dest[1] = (color >> 8) + 128; /* V */
1859                     /* R */ Dest[2] = (color) + 128;      /* U */
1860                     Dest += 3;
1861                 }
1862             }
1863             break;
1864         }
1865
1866         case CONVERT_V16U16:
1867         {
1868             unsigned int x, y;
1869             DWORD *Source;
1870             unsigned short *Dest;
1871             for(y = 0; y < height; y++) {
1872                 Source = (DWORD *) (src + y * pitch);
1873                 Dest = (unsigned short *) (dst + y * outpitch);
1874                 for (x = 0; x < width; x++ ) {
1875                     DWORD color = (*Source++);
1876                     /* B */ Dest[0] = 0xffff;
1877                     /* G */ Dest[1] = (color >> 16) + 32768; /* V */
1878                     /* R */ Dest[2] = (color      ) + 32768; /* U */
1879                     Dest += 3;
1880                 }
1881             }
1882             break;
1883         }
1884
1885         case CONVERT_Q8W8V8U8:
1886         {
1887             unsigned int x, y;
1888             DWORD *Source;
1889             unsigned char *Dest;
1890             for(y = 0; y < height; y++) {
1891                 Source = (DWORD *) (src + y * pitch);
1892                 Dest = dst + y * outpitch;
1893                 for (x = 0; x < width; x++ ) {
1894                     long color = (*Source++);
1895                     /* B */ Dest[0] = ((color >> 16) & 0xff) + 128; /* W */
1896                     /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
1897                     /* R */ Dest[2] = (color         & 0xff) + 128; /* U */
1898                     /* A */ Dest[3] = ((color >> 24) & 0xff) + 128; /* Q */
1899                     Dest += 4;
1900                 }
1901             }
1902             break;
1903         }
1904
1905         case CONVERT_L6V5U5:
1906         {
1907             unsigned int x, y;
1908             WORD *Source;
1909             unsigned char *Dest;
1910
1911             if(GL_SUPPORT(NV_TEXTURE_SHADER)) {
1912                 /* This makes the gl surface bigger(24 bit instead of 16), but it works with
1913                  * fixed function and shaders without further conversion once the surface is
1914                  * loaded
1915                  */
1916                 for(y = 0; y < height; y++) {
1917                     Source = (WORD *) (src + y * pitch);
1918                     Dest = dst + y * outpitch;
1919                     for (x = 0; x < width; x++ ) {
1920                         short color = (*Source++);
1921                         unsigned char l = ((color >> 10) & 0xfc);
1922                                   char v = ((color >>  5) & 0x3e);
1923                                   char u = ((color      ) & 0x1f);
1924
1925                         /* 8 bits destination, 6 bits source, 8th bit is the sign. gl ignores the sign
1926                          * and doubles the positive range. Thus shift left only once, gl does the 2nd
1927                          * shift. GL reads a signed value and converts it into an unsigned value.
1928                          */
1929                         /* M */ Dest[2] = l << 1;
1930
1931                         /* Those are read as signed, but kept signed. Just left-shift 3 times to scale
1932                          * from 5 bit values to 8 bit values.
1933                          */
1934                         /* V */ Dest[1] = v << 3;
1935                         /* U */ Dest[0] = u << 3;
1936                         Dest += 3;
1937                     }
1938                 }
1939             } else {
1940                 for(y = 0; y < height; y++) {
1941                     unsigned short *Dest_s = (unsigned short *) (dst + y * outpitch);
1942                     Source = (WORD *) (src + y * pitch);
1943                     for (x = 0; x < width; x++ ) {
1944                         short color = (*Source++);
1945                         unsigned char l = ((color >> 10) & 0xfc);
1946                                  short v = ((color >>  5) & 0x3e);
1947                                  short u = ((color      ) & 0x1f);
1948                         short v_conv = v + 16;
1949                         short u_conv = u + 16;
1950
1951                         *Dest_s = ((v_conv << 11) & 0xf800) | ((l << 5) & 0x7e0) | (u_conv & 0x1f);
1952                         Dest_s += 1;
1953                     }
1954                 }
1955             }
1956             break;
1957         }
1958
1959         case CONVERT_X8L8V8U8:
1960         {
1961             unsigned int x, y;
1962             DWORD *Source;
1963             unsigned char *Dest;
1964
1965             if(GL_SUPPORT(NV_TEXTURE_SHADER)) {
1966                 /* This implementation works with the fixed function pipeline and shaders
1967                  * without further modification after converting the surface.
1968                  */
1969                 for(y = 0; y < height; y++) {
1970                     Source = (DWORD *) (src + y * pitch);
1971                     Dest = dst + y * outpitch;
1972                     for (x = 0; x < width; x++ ) {
1973                         long color = (*Source++);
1974                         /* L */ Dest[2] = ((color >> 16) & 0xff);   /* L */
1975                         /* V */ Dest[1] = ((color >> 8 ) & 0xff);   /* V */
1976                         /* U */ Dest[0] = (color         & 0xff);   /* U */
1977                         /* I */ Dest[3] = 255;                      /* X */
1978                         Dest += 4;
1979                     }
1980                 }
1981             } else {
1982                 /* Doesn't work correctly with the fixed function pipeline, but can work in
1983                  * shaders if the shader is adjusted. (There's no use for this format in gl's
1984                  * standard fixed function pipeline anyway).
1985                  */
1986                 for(y = 0; y < height; y++) {
1987                     Source = (DWORD *) (src + y * pitch);
1988                     Dest = dst + y * outpitch;
1989                     for (x = 0; x < width; x++ ) {
1990                         long color = (*Source++);
1991                         /* B */ Dest[0] = ((color >> 16) & 0xff);       /* L */
1992                         /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
1993                         /* R */ Dest[2] = (color         & 0xff) + 128;  /* U */
1994                         Dest += 4;
1995                     }
1996                 }
1997             }
1998             break;
1999         }
2000
2001         case CONVERT_A4L4:
2002         {
2003             unsigned int x, y;
2004             unsigned char *Source;
2005             unsigned char *Dest;
2006             for(y = 0; y < height; y++) {
2007                 Source = src + y * pitch;
2008                 Dest = dst + y * outpitch;
2009                 for (x = 0; x < width; x++ ) {
2010                     unsigned char color = (*Source++);
2011                     /* A */ Dest[1] = (color & 0xf0) << 0;
2012                     /* L */ Dest[0] = (color & 0x0f) << 4;
2013                     Dest += 2;
2014                 }
2015             }
2016             break;
2017         }
2018
2019         case CONVERT_R32F:
2020         {
2021             unsigned int x, y;
2022             float *Source;
2023             float *Dest;
2024             for(y = 0; y < height; y++) {
2025                 Source = (float *) (src + y * pitch);
2026                 Dest = (float *) (dst + y * outpitch);
2027                 for (x = 0; x < width; x++ ) {
2028                     float color = (*Source++);
2029                     Dest[0] = color;
2030                     Dest[1] = 1.0;
2031                     Dest[2] = 1.0;
2032                     Dest += 3;
2033                 }
2034             }
2035             break;
2036         }
2037
2038         case CONVERT_R16F:
2039         {
2040             unsigned int x, y;
2041             WORD *Source;
2042             WORD *Dest;
2043             WORD one = 0x3c00;
2044             for(y = 0; y < height; y++) {
2045                 Source = (WORD *) (src + y * pitch);
2046                 Dest = (WORD *) (dst + y * outpitch);
2047                 for (x = 0; x < width; x++ ) {
2048                     WORD color = (*Source++);
2049                     Dest[0] = color;
2050                     Dest[1] = one;
2051                     Dest[2] = one;
2052                     Dest += 3;
2053                 }
2054             }
2055             break;
2056         }
2057
2058         case CONVERT_G16R16:
2059         {
2060             unsigned int x, y;
2061             WORD *Source;
2062             WORD *Dest;
2063
2064             for(y = 0; y < height; y++) {
2065                 Source = (WORD *) (src + y * pitch);
2066                 Dest = (WORD *) (dst + y * outpitch);
2067                 for (x = 0; x < width; x++ ) {
2068                     WORD green = (*Source++);
2069                     WORD red = (*Source++);
2070                     Dest[0] = green;
2071                     Dest[1] = red;
2072                     Dest[2] = 0xffff;
2073                     Dest += 3;
2074                 }
2075             }
2076             break;
2077         }
2078
2079         default:
2080             ERR("Unsupported conversation type %d\n", convert);
2081     }
2082     return WINED3D_OK;
2083 }
2084
2085 static void d3dfmt_p8_init_palette(IWineD3DSurfaceImpl *This, BYTE table[256][4], BOOL colorkey) {
2086     IWineD3DPaletteImpl* pal = This->palette;
2087     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2088     BOOL index_in_alpha = FALSE;
2089     int dxVersion = ( (IWineD3DImpl *) device->wineD3D)->dxVersion;
2090     int i;
2091
2092     /* Old games like StarCraft, C&C, Red Alert and others use P8 render targets.
2093     * Reading back the RGB output each lockrect (each frame as they lock the whole screen)
2094     * is slow. Further RGB->P8 conversion is not possible because palettes can have
2095     * duplicate entries. Store the color key in the unused alpha component to speed the
2096     * download up and to make conversion unneeded. */
2097     index_in_alpha = primary_render_target_is_p8(device);
2098
2099     if (pal == NULL) {
2100         /* In DirectDraw the palette is a property of the surface, there are no such things as device palettes. */
2101         if(dxVersion <= 7) {
2102             ERR("This code should never get entered for DirectDraw!, expect problems\n");
2103             if(index_in_alpha) {
2104                 /* Guarantees that memory representation remains correct after sysmem<->texture transfers even if
2105                    there's no palette at this time. */
2106                 for (i = 0; i < 256; i++) table[i][3] = i;
2107             }
2108         } else {
2109             /*  Direct3D >= 8 palette usage style: P8 textures use device palettes, palette entry format is A8R8G8B8,
2110                 alpha is stored in peFlags and may be used by the app if D3DPTEXTURECAPS_ALPHAPALETTE device
2111                 capability flag is present (wine does advertise this capability) */
2112             for (i = 0; i < 256; i++) {
2113                 table[i][0] = device->palettes[device->currentPalette][i].peRed;
2114                 table[i][1] = device->palettes[device->currentPalette][i].peGreen;
2115                 table[i][2] = device->palettes[device->currentPalette][i].peBlue;
2116                 table[i][3] = device->palettes[device->currentPalette][i].peFlags;
2117             }
2118         }
2119     } else {
2120         TRACE("Using surface palette %p\n", pal);
2121         /* Get the surface's palette */
2122         for (i = 0; i < 256; i++) {
2123             table[i][0] = pal->palents[i].peRed;
2124             table[i][1] = pal->palents[i].peGreen;
2125             table[i][2] = pal->palents[i].peBlue;
2126
2127             /* When index_in_alpha is the palette index is stored in the alpha component. In case of a readback
2128                we can then read GL_ALPHA. Color keying is handled in BltOverride using a GL_ALPHA_TEST using GL_NOT_EQUAL.
2129                In case of index_in_alpha the color key itself is passed to glAlphaFunc in other cases the alpha component
2130                of pixels that should be masked away is set to 0. */
2131             if(index_in_alpha) {
2132                 table[i][3] = i;
2133             } else if(colorkey && (i >= This->SrcBltCKey.dwColorSpaceLowValue) &&  (i <= This->SrcBltCKey.dwColorSpaceHighValue)) {
2134                 table[i][3] = 0x00;
2135             } else if(pal->Flags & WINEDDPCAPS_ALPHA) {
2136                 table[i][3] = pal->palents[i].peFlags;
2137             } else {
2138                 table[i][3] = 0xFF;
2139             }
2140         }
2141     }
2142 }
2143
2144 const char *fragment_palette_conversion =
2145     "!!ARBfp1.0\n"
2146     "TEMP index;\n"
2147     "PARAM constants = { 0.996, 0.00195, 0, 0 };\n" /* { 255/256, 0.5/255*255/256, 0, 0 } */
2148     "TEX index, fragment.texcoord[0], texture[0], 2D;\n" /* The alpha-component contains the palette index */
2149     "MAD index.a, index.a, constants.x, constants.y;\n" /* Scale the index by 255/256 and add a bias of '0.5' in order to sample in the middle */
2150     "TEX result.color, index.a, texture[1], 1D;\n" /* use the alpha-component as a index in the palette to get the final color */
2151     "END";
2152
2153 /* This function is used in case of 8bit paletted textures to upload the palette.
2154    It supports GL_EXT_paletted_texture and GL_ARB_fragment_program, support for other
2155    extensions like ATI_fragment_shaders is possible.
2156 */
2157 static void d3dfmt_p8_upload_palette(IWineD3DSurface *iface, CONVERT_TYPES convert) {
2158     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2159     BYTE table[256][4];
2160     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2161
2162     d3dfmt_p8_init_palette(This, table, (convert == CONVERT_PALETTED_CK));
2163
2164     /* Try to use the paletted texture extension */
2165     if(GL_SUPPORT(EXT_PALETTED_TEXTURE))
2166     {
2167         TRACE("Using GL_EXT_PALETTED_TEXTURE for 8-bit paletted texture support\n");
2168         GL_EXTCALL(glColorTableEXT(This->glDescription.target,GL_RGBA,256,GL_RGBA,GL_UNSIGNED_BYTE, table));
2169     }
2170     else
2171     {
2172         /* Let a fragment shader do the color conversion by uploading the palette to a 1D texture.
2173          * The 8bit pixel data will be used as an index in this palette texture to retrieve the final color. */
2174         TRACE("Using fragment shaders for emulating 8-bit paletted texture support\n");
2175
2176         /* Create the fragment program if we don't have it */
2177         if(!device->paletteConversionShader)
2178         {
2179             glEnable(GL_FRAGMENT_PROGRAM_ARB);
2180             GL_EXTCALL(glGenProgramsARB(1, &device->paletteConversionShader));
2181             GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, device->paletteConversionShader));
2182             GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fragment_palette_conversion), (const GLbyte *)fragment_palette_conversion));
2183             glDisable(GL_FRAGMENT_PROGRAM_ARB);
2184         }
2185
2186         glEnable(GL_FRAGMENT_PROGRAM_ARB);
2187         GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, device->paletteConversionShader));
2188
2189         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE1));
2190         glEnable(GL_TEXTURE_1D);
2191         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2192
2193         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2194         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); /* Make sure we have discrete color levels. */
2195         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2196         glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, table); /* Upload the palette */
2197
2198         /* Switch back to unit 0 in which the 2D texture will be stored. */
2199         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0));
2200
2201         /* Rebind the texture because it isn't bound anymore */
2202         glBindTexture(This->glDescription.target, This->glDescription.textureName);
2203     }
2204 }
2205
2206 BOOL palette9_changed(IWineD3DSurfaceImpl *This) {
2207     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2208
2209     if(This->palette || (This->resource.format != WINED3DFMT_P8 && This->resource.format != WINED3DFMT_A8P8)) {
2210         /* If a ddraw-style palette is attached assume no d3d9 palette change.
2211          * Also the palette isn't interesting if the surface format isn't P8 or A8P8
2212          */
2213         return FALSE;
2214     }
2215
2216     if(This->palette9) {
2217         if(memcmp(This->palette9, &device->palettes[device->currentPalette], sizeof(PALETTEENTRY) * 256) == 0) {
2218             return FALSE;
2219         }
2220     } else {
2221         This->palette9 = HeapAlloc(GetProcessHeap(), 0, sizeof(PALETTEENTRY) * 256);
2222     }
2223     memcpy(This->palette9, &device->palettes[device->currentPalette], sizeof(PALETTEENTRY) * 256);
2224     return TRUE;
2225 }
2226
2227 static inline void clear_unused_channels(IWineD3DSurfaceImpl *This) {
2228     GLboolean oldwrite[4];
2229
2230     /* Some formats have only some color channels, and the others are 1.0.
2231      * since our rendering renders to all channels, and those pixel formats
2232      * are emulated by using a full texture with the other channels set to 1.0
2233      * manually, clear the unused channels.
2234      *
2235      * This could be done with hacking colorwriteenable to mask the colors,
2236      * but before drawing the buffer would have to be cleared too, so there's
2237      * no gain in that
2238      */
2239     switch(This->resource.format) {
2240         case WINED3DFMT_R16F:
2241         case WINED3DFMT_R32F:
2242             TRACE("R16F or R32F format, clearing green, blue and alpha to 1.0\n");
2243             /* Do not activate a context, the correct drawable is active already
2244              * though just the read buffer is set, make sure to have the correct draw
2245              * buffer too
2246              */
2247             glDrawBuffer(This->resource.wineD3DDevice->offscreenBuffer);
2248             glDisable(GL_SCISSOR_TEST);
2249             glGetBooleanv(GL_COLOR_WRITEMASK, oldwrite);
2250             glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
2251             glClearColor(0.0, 1.0, 1.0, 1.0);
2252             glClear(GL_COLOR_BUFFER_BIT);
2253             glColorMask(oldwrite[0], oldwrite[1], oldwrite[2], oldwrite[3]);
2254             if(!This->resource.wineD3DDevice->render_offscreen) glDrawBuffer(GL_BACK);
2255             checkGLcall("Unused channel clear\n");
2256             break;
2257
2258         default: break;
2259     }
2260 }
2261
2262 static HRESULT WINAPI IWineD3DSurfaceImpl_LoadTexture(IWineD3DSurface *iface, BOOL srgb_mode) {
2263     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2264
2265     if (!(This->Flags & SFLAG_INTEXTURE)) {
2266         TRACE("Reloading because surface is dirty\n");
2267     } else if(/* Reload: gl texture has ck, now no ckey is set OR */
2268               ((This->Flags & SFLAG_GLCKEY) && (!(This->CKeyFlags & WINEDDSD_CKSRCBLT))) ||
2269               /* Reload: vice versa  OR */
2270               ((!(This->Flags & SFLAG_GLCKEY)) && (This->CKeyFlags & WINEDDSD_CKSRCBLT)) ||
2271               /* Also reload: Color key is active AND the color key has changed */
2272               ((This->CKeyFlags & WINEDDSD_CKSRCBLT) && (
2273                 (This->glCKey.dwColorSpaceLowValue != This->SrcBltCKey.dwColorSpaceLowValue) ||
2274                 (This->glCKey.dwColorSpaceHighValue != This->SrcBltCKey.dwColorSpaceHighValue)))) {
2275         TRACE("Reloading because of color keying\n");
2276         /* To perform the color key conversion we need a sysmem copy of
2277          * the surface. Make sure we have it
2278          */
2279
2280         IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL);
2281         /* Make sure the texture is reloaded because of the color key change, this kills performance though :( */
2282         /* TODO: This is not necessarily needed with hw palettized texture support */
2283         IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE);
2284     } else {
2285         TRACE("surface is already in texture\n");
2286         return WINED3D_OK;
2287     }
2288
2289     /* Resources are placed in system RAM and do not need to be recreated when a device is lost.
2290      *  These resources are not bound by device size or format restrictions. Because of this,
2291      *  these resources cannot be accessed by the Direct3D device nor set as textures or render targets.
2292      *  However, these resources can always be created, locked, and copied.
2293      */
2294     if (This->resource.pool == WINED3DPOOL_SCRATCH )
2295     {
2296         FIXME("(%p) Operation not supported for scratch textures\n",This);
2297         return WINED3DERR_INVALIDCALL;
2298     }
2299
2300     This->srgb = srgb_mode;
2301     IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL /* no partial locking for textures yet */);
2302
2303 #if 0
2304     {
2305         static unsigned int gen = 0;
2306         char buffer[4096];
2307         ++gen;
2308         if ((gen % 10) == 0) {
2309             snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, This->glDescription.target, This->glDescription.level, gen);
2310             IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer);
2311         }
2312         /*
2313          * debugging crash code
2314          if (gen == 250) {
2315          void** test = NULL;
2316          *test = 0;
2317          }
2318          */
2319     }
2320 #endif
2321
2322     if (!(This->Flags & SFLAG_DONOTFREE)) {
2323         HeapFree(GetProcessHeap(), 0, This->resource.heapMemory);
2324         This->resource.allocatedMemory = NULL;
2325         This->resource.heapMemory = NULL;
2326         IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, FALSE);
2327     }
2328
2329     return WINED3D_OK;
2330 }
2331
2332 static void WINAPI IWineD3DSurfaceImpl_BindTexture(IWineD3DSurface *iface) {
2333     /* TODO: check for locks */
2334     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2335     IWineD3DBaseTexture *baseTexture = NULL;
2336     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
2337
2338     TRACE("(%p)Checking to see if the container is a base texture\n", This);
2339     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
2340         TRACE("Passing to container\n");
2341         IWineD3DBaseTexture_BindTexture(baseTexture);
2342         IWineD3DBaseTexture_Release(baseTexture);
2343     } else {
2344         TRACE("(%p) : Binding surface\n", This);
2345
2346         if(!device->isInDraw) {
2347             ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
2348         }
2349
2350         ENTER_GL();
2351
2352         glEnable(This->glDescription.target);
2353
2354         if (!This->glDescription.level) {
2355             if (!This->glDescription.textureName) {
2356                 glGenTextures(1, &This->glDescription.textureName);
2357                 checkGLcall("glGenTextures");
2358                 TRACE("Surface %p given name %d\n", This, This->glDescription.textureName);
2359             }
2360             /* This is where we should be reducing the amount of GLMemoryUsed */
2361         } else if (This->glDescription.textureName) {
2362             /* Mipmap surfaces should have a base texture container */
2363             ERR("Mipmap surface has a glTexture bound to it!\n");
2364         }
2365
2366         glBindTexture(This->glDescription.target, This->glDescription.textureName);
2367         checkGLcall("glBindTexture");
2368
2369         LEAVE_GL();
2370     }
2371     return;
2372 }
2373
2374 #include <errno.h>
2375 #include <stdio.h>
2376 HRESULT WINAPI IWineD3DSurfaceImpl_SaveSnapshot(IWineD3DSurface *iface, const char* filename) {
2377     FILE* f = NULL;
2378     UINT i, y;
2379     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2380     char *allocatedMemory;
2381     char *textureRow;
2382     IWineD3DSwapChain *swapChain = NULL;
2383     int width, height;
2384     GLuint tmpTexture = 0;
2385     DWORD color;
2386     /*FIXME:
2387     Textures may not be stored in ->allocatedgMemory and a GlTexture
2388     so we should lock the surface before saving a snapshot, or at least check that
2389     */
2390     /* TODO: Compressed texture images can be obtained from the GL in uncompressed form
2391     by calling GetTexImage and in compressed form by calling
2392     GetCompressedTexImageARB.  Queried compressed images can be saved and
2393     later reused by calling CompressedTexImage[123]DARB.  Pre-compressed
2394     texture images do not need to be processed by the GL and should
2395     significantly improve texture loading performance relative to uncompressed
2396     images. */
2397
2398 /* Setup the width and height to be the internal texture width and height. */
2399     width  = This->pow2Width;
2400     height = This->pow2Height;
2401 /* check to see if we're a 'virtual' texture, e.g. we're not a pbuffer of texture, we're a back buffer*/
2402     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapChain);
2403
2404     if (This->Flags & SFLAG_INDRAWABLE && !(This->Flags & SFLAG_INTEXTURE)) {
2405         /* if were not a real texture then read the back buffer into a real texture */
2406         /* we don't want to interfere with the back buffer so read the data into a temporary
2407          * texture and then save the data out of the temporary texture
2408          */
2409         GLint prevRead;
2410         ENTER_GL();
2411         TRACE("(%p) Reading render target into texture\n", This);
2412         glEnable(GL_TEXTURE_2D);
2413
2414         glGenTextures(1, &tmpTexture);
2415         glBindTexture(GL_TEXTURE_2D, tmpTexture);
2416
2417         glTexImage2D(GL_TEXTURE_2D,
2418                         0,
2419                         GL_RGBA,
2420                         width,
2421                         height,
2422                         0/*border*/,
2423                         GL_RGBA,
2424                         GL_UNSIGNED_INT_8_8_8_8_REV,
2425                         NULL);
2426
2427         glGetIntegerv(GL_READ_BUFFER, &prevRead);
2428         vcheckGLcall("glGetIntegerv");
2429         glReadBuffer(swapChain ? GL_BACK : This->resource.wineD3DDevice->offscreenBuffer);
2430         vcheckGLcall("glReadBuffer");
2431         glCopyTexImage2D(GL_TEXTURE_2D,
2432                             0,
2433                             GL_RGBA,
2434                             0,
2435                             0,
2436                             width,
2437                             height,
2438                             0);
2439
2440         checkGLcall("glCopyTexImage2D");
2441         glReadBuffer(prevRead);
2442         LEAVE_GL();
2443
2444     } else { /* bind the real texture, and make sure it up to date */
2445         IWineD3DSurface_PreLoad(iface);
2446     }
2447     allocatedMemory = HeapAlloc(GetProcessHeap(), 0, width  * height * 4);
2448     ENTER_GL();
2449     FIXME("Saving texture level %d width %d height %d\n", This->glDescription.level, width, height);
2450     glGetTexImage(GL_TEXTURE_2D,
2451                 This->glDescription.level,
2452                 GL_RGBA,
2453                 GL_UNSIGNED_INT_8_8_8_8_REV,
2454                 allocatedMemory);
2455     checkGLcall("glTexImage2D");
2456     if (tmpTexture) {
2457         glBindTexture(GL_TEXTURE_2D, 0);
2458         glDeleteTextures(1, &tmpTexture);
2459     }
2460     LEAVE_GL();
2461
2462     f = fopen(filename, "w+");
2463     if (NULL == f) {
2464         ERR("opening of %s failed with: %s\n", filename, strerror(errno));
2465         return WINED3DERR_INVALIDCALL;
2466     }
2467 /* Save the data out to a TGA file because 1: it's an easy raw format, 2: it supports an alpha channel */
2468     TRACE("(%p) opened %s with format %s\n", This, filename, debug_d3dformat(This->resource.format));
2469 /* TGA header */
2470     fputc(0,f);
2471     fputc(0,f);
2472     fputc(2,f);
2473     fputc(0,f);
2474     fputc(0,f);
2475     fputc(0,f);
2476     fputc(0,f);
2477     fputc(0,f);
2478     fputc(0,f);
2479     fputc(0,f);
2480     fputc(0,f);
2481     fputc(0,f);
2482 /* short width*/
2483     fwrite(&width,2,1,f);
2484 /* short height */
2485     fwrite(&height,2,1,f);
2486 /* format rgba */
2487     fputc(0x20,f);
2488     fputc(0x28,f);
2489 /* raw data */
2490     /* 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 */
2491     if(swapChain)
2492         textureRow = allocatedMemory + (width * (height - 1) *4);
2493     else
2494         textureRow = allocatedMemory;
2495     for (y = 0 ; y < height; y++) {
2496         for (i = 0; i < width;  i++) {
2497             color = *((DWORD*)textureRow);
2498             fputc((color >> 16) & 0xFF, f); /* B */
2499             fputc((color >>  8) & 0xFF, f); /* G */
2500             fputc((color >>  0) & 0xFF, f); /* R */
2501             fputc((color >> 24) & 0xFF, f); /* A */
2502             textureRow += 4;
2503         }
2504         /* take two rows of the pointer to the texture memory */
2505         if(swapChain)
2506             (textureRow-= width << 3);
2507
2508     }
2509     TRACE("Closing file\n");
2510     fclose(f);
2511
2512     if(swapChain) {
2513         IWineD3DSwapChain_Release(swapChain);
2514     }
2515     HeapFree(GetProcessHeap(), 0, allocatedMemory);
2516     return WINED3D_OK;
2517 }
2518
2519 /**
2520  *   Slightly inefficient way to handle multiple dirty rects but it works :)
2521  */
2522 HRESULT WINAPI IWineD3DSurfaceImpl_AddDirtyRect(IWineD3DSurface *iface, CONST RECT* pDirtyRect) {
2523     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2524     IWineD3DBaseTexture *baseTexture = NULL;
2525
2526     if (!(This->Flags & SFLAG_INSYSMEM) && (This->Flags & SFLAG_INTEXTURE))
2527         IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL /* no partial locking for textures yet */);
2528
2529     IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE);
2530     if (NULL != pDirtyRect) {
2531         This->dirtyRect.left   = min(This->dirtyRect.left,   pDirtyRect->left);
2532         This->dirtyRect.top    = min(This->dirtyRect.top,    pDirtyRect->top);
2533         This->dirtyRect.right  = max(This->dirtyRect.right,  pDirtyRect->right);
2534         This->dirtyRect.bottom = max(This->dirtyRect.bottom, pDirtyRect->bottom);
2535     } else {
2536         This->dirtyRect.left   = 0;
2537         This->dirtyRect.top    = 0;
2538         This->dirtyRect.right  = This->currentDesc.Width;
2539         This->dirtyRect.bottom = This->currentDesc.Height;
2540     }
2541     TRACE("(%p) : Dirty: yes, Rect:(%d,%d,%d,%d)\n", This, This->dirtyRect.left,
2542           This->dirtyRect.top, This->dirtyRect.right, This->dirtyRect.bottom);
2543     /* if the container is a basetexture then mark it dirty. */
2544     if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&baseTexture) == WINED3D_OK) {
2545         TRACE("Passing to container\n");
2546         IWineD3DBaseTexture_SetDirty(baseTexture, TRUE);
2547         IWineD3DBaseTexture_Release(baseTexture);
2548     }
2549     return WINED3D_OK;
2550 }
2551
2552 HRESULT WINAPI IWineD3DSurfaceImpl_SetFormat(IWineD3DSurface *iface, WINED3DFORMAT format) {
2553     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2554     HRESULT hr;
2555     const GlPixelFormatDesc *glDesc;
2556     getFormatDescEntry(format, &GLINFO_LOCATION, &glDesc);
2557
2558     TRACE("(%p) : Calling base function first\n", This);
2559     hr = IWineD3DBaseSurfaceImpl_SetFormat(iface, format);
2560     if(SUCCEEDED(hr)) {
2561         /* Setup some glformat defaults */
2562         This->glDescription.glFormat         = glDesc->glFormat;
2563         This->glDescription.glFormatInternal = glDesc->glInternal;
2564         This->glDescription.glType           = glDesc->glType;
2565
2566         This->Flags &= ~SFLAG_ALLOCATED;
2567         TRACE("(%p) : glFormat %d, glFotmatInternal %d, glType %d\n", This,
2568               This->glDescription.glFormat, This->glDescription.glFormatInternal, This->glDescription.glType);
2569     }
2570     return hr;
2571 }
2572
2573 HRESULT WINAPI IWineD3DSurfaceImpl_SetMem(IWineD3DSurface *iface, void *Mem) {
2574     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
2575
2576     if(This->Flags & (SFLAG_LOCKED | SFLAG_DCINUSE)) {
2577         WARN("Surface is locked or the HDC is in use\n");
2578         return WINED3DERR_INVALIDCALL;
2579     }
2580
2581     if(Mem && Mem != This->resource.allocatedMemory) {
2582         void *release = NULL;
2583
2584         /* Do I have to copy the old surface content? */
2585         if(This->Flags & SFLAG_DIBSECTION) {
2586                 /* Release the DC. No need to hold the critical section for the update
2587                  * Thread because this thread runs only on front buffers, but this method
2588                  * fails for render targets in the check above.
2589                  */
2590                 SelectObject(This->hDC, This->dib.holdbitmap);
2591                 DeleteDC(This->hDC);
2592                 /* Release the DIB section */
2593                 DeleteObject(This->dib.DIBsection);
2594                 This->dib.bitmap_data = NULL;
2595                 This->resource.allocatedMemory = NULL;
2596                 This->hDC = NULL;
2597                 This->Flags &= ~SFLAG_DIBSECTION;
2598         } else if(!(This->Flags & SFLAG_USERPTR)) {
2599             release = This->resource.heapMemory;
2600             This->resource.heapMemory = NULL;
2601         }
2602         This->resource.allocatedMemory = Mem;
2603         This->Flags |= SFLAG_USERPTR | SFLAG_INSYSMEM;
2604
2605         /* Now the surface memory is most up do date. Invalidate drawable and texture */
2606         IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE);
2607
2608         /* For client textures opengl has to be notified */
2609         if(This->Flags & SFLAG_CLIENT) {
2610             This->Flags &= ~SFLAG_ALLOCATED;
2611             IWineD3DSurface_PreLoad(iface);
2612             /* And hope that the app behaves correctly and did not free the old surface memory before setting a new pointer */
2613         }
2614
2615         /* Now free the old memory if any */
2616         HeapFree(GetProcessHeap(), 0, release);
2617     } else if(This->Flags & SFLAG_USERPTR) {
2618         /* LockRect and GetDC will re-create the dib section and allocated memory */
2619         This->resource.allocatedMemory = NULL;
2620         /* HeapMemory should be NULL already */
2621         if(This->resource.heapMemory != NULL) ERR("User pointer surface has heap memory allocated\n");
2622         This->Flags &= ~SFLAG_USERPTR;
2623
2624         if(This->Flags & SFLAG_CLIENT) {
2625             This->Flags &= ~SFLAG_ALLOCATED;
2626             /* This respecifies an empty texture and opengl knows that the old memory is gone */
2627             IWineD3DSurface_PreLoad(iface);
2628         }
2629     }
2630     return WINED3D_OK;
2631 }
2632
2633 void flip_surface(IWineD3DSurfaceImpl *front, IWineD3DSurfaceImpl *back) {
2634
2635     /* Flip the surface contents */
2636     /* Flip the DC */
2637     {
2638         HDC tmp;
2639         tmp = front->hDC;
2640         front->hDC = back->hDC;
2641         back->hDC = tmp;
2642     }
2643
2644     /* Flip the DIBsection */
2645     {
2646         HBITMAP tmp;
2647         BOOL hasDib = front->Flags & SFLAG_DIBSECTION;
2648         tmp = front->dib.DIBsection;
2649         front->dib.DIBsection = back->dib.DIBsection;
2650         back->dib.DIBsection = tmp;
2651
2652         if(back->Flags & SFLAG_DIBSECTION) front->Flags |= SFLAG_DIBSECTION;
2653         else front->Flags &= ~SFLAG_DIBSECTION;
2654         if(hasDib) back->Flags |= SFLAG_DIBSECTION;
2655         else back->Flags &= ~SFLAG_DIBSECTION;
2656     }
2657
2658     /* Flip the surface data */
2659     {
2660         void* tmp;
2661
2662         tmp = front->dib.bitmap_data;
2663         front->dib.bitmap_data = back->dib.bitmap_data;
2664         back->dib.bitmap_data = tmp;
2665
2666         tmp = front->resource.allocatedMemory;
2667         front->resource.allocatedMemory = back->resource.allocatedMemory;
2668         back->resource.allocatedMemory = tmp;
2669
2670         tmp = front->resource.heapMemory;
2671         front->resource.heapMemory = back->resource.heapMemory;
2672         back->resource.heapMemory = tmp;
2673     }
2674
2675     /* Flip the PBO */
2676     {
2677         GLuint tmp_pbo = front->pbo;
2678         front->pbo = back->pbo;
2679         back->pbo = tmp_pbo;
2680     }
2681
2682     /* client_memory should not be different, but just in case */
2683     {
2684         BOOL tmp;
2685         tmp = front->dib.client_memory;
2686         front->dib.client_memory = back->dib.client_memory;
2687         back->dib.client_memory = tmp;
2688     }
2689
2690     /* Flip the opengl texture */
2691     {
2692         glDescriptor tmp_desc = back->glDescription;
2693         back->glDescription = front->glDescription;
2694         front->glDescription = tmp_desc;
2695     }
2696
2697     {
2698         DWORD tmp_flags = back->Flags;
2699         back->Flags = front->Flags;
2700         front->Flags = tmp_flags;
2701     }
2702 }
2703
2704 static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DSurface *override, DWORD Flags) {
2705     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
2706     IWineD3DSwapChainImpl *swapchain = NULL;
2707     HRESULT hr;
2708     TRACE("(%p)->(%p,%x)\n", This, override, Flags);
2709
2710     /* Flipping is only supported on RenderTargets and overlays*/
2711     if( !(This->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_OVERLAY)) ) {
2712         WARN("Tried to flip a non-render target, non-overlay surface\n");
2713         return WINEDDERR_NOTFLIPPABLE;
2714     }
2715
2716     if(This->resource.usage & WINED3DUSAGE_OVERLAY) {
2717         flip_surface(This, (IWineD3DSurfaceImpl *) override);
2718
2719         /* Update the overlay if it is visible */
2720         if(This->overlay_dest) {
2721             return IWineD3DSurface_DrawOverlay((IWineD3DSurface *) This);
2722         } else {
2723             return WINED3D_OK;
2724         }
2725     }
2726
2727     if(override) {
2728         /* DDraw sets this for the X11 surfaces, so don't confuse the user 
2729          * FIXME("(%p) Target override is not supported by now\n", This);
2730          * Additionally, it isn't really possible to support triple-buffering
2731          * properly on opengl at all
2732          */
2733     }
2734
2735     IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **) &swapchain);
2736     if(!swapchain) {
2737         ERR("Flipped surface is not on a swapchain\n");
2738         return WINEDDERR_NOTFLIPPABLE;
2739     }
2740
2741     /* Just overwrite the swapchain presentation interval. This is ok because only ddraw apps can call Flip,
2742      * and only d3d8 and d3d9 apps specify the presentation interval
2743      */
2744     if((Flags & (WINEDDFLIP_NOVSYNC | WINEDDFLIP_INTERVAL2 | WINEDDFLIP_INTERVAL3 | WINEDDFLIP_INTERVAL4)) == 0) {
2745         /* Most common case first to avoid wasting time on all the other cases */
2746         swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_ONE;
2747     } else if(Flags & WINEDDFLIP_NOVSYNC) {
2748         swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_IMMEDIATE;
2749     } else if(Flags & WINEDDFLIP_INTERVAL2) {
2750         swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_TWO;
2751     } else if(Flags & WINEDDFLIP_INTERVAL3) {
2752         swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_THREE;
2753     } else {
2754         swapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_FOUR;
2755     }
2756
2757     /* Flipping a OpenGL surface -> Use WineD3DDevice::Present */
2758     hr = IWineD3DSwapChain_Present((IWineD3DSwapChain *) swapchain, NULL, NULL, 0, NULL, 0);
2759     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
2760     return hr;
2761 }
2762
2763 /* Does a direct frame buffer -> texture copy. Stretching is done
2764  * with single pixel copy calls
2765  */
2766 static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3DSurface *SrcSurface, IWineD3DSwapChainImpl *swapchain, WINED3DRECT *srect, WINED3DRECT *drect, BOOL upsidedown, WINED3DTEXTUREFILTERTYPE Filter) {
2767     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
2768     float xrel, yrel;
2769     UINT row;
2770     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2771
2772
2773     ActivateContext(myDevice, SrcSurface, CTXUSAGE_BLIT);
2774     IWineD3DSurface_PreLoad((IWineD3DSurface *) This);
2775     ENTER_GL();
2776
2777     /* TODO: Do we need GL_TEXTURE_2D enabled fpr copyteximage? */
2778     glEnable(This->glDescription.target);
2779     checkGLcall("glEnable(This->glDescription.target)");
2780
2781     /* Bind the target texture */
2782     glBindTexture(This->glDescription.target, This->glDescription.textureName);
2783     checkGLcall("glBindTexture");
2784     if(!swapchain) {
2785         TRACE("Reading from an offscreen target\n");
2786         upsidedown = !upsidedown;
2787         glReadBuffer(myDevice->offscreenBuffer);
2788     } else {
2789         GLenum buffer = surface_get_gl_buffer(SrcSurface, (IWineD3DSwapChain *)swapchain);
2790         glReadBuffer(buffer);
2791     }
2792     checkGLcall("glReadBuffer");
2793
2794     xrel = (float) (srect->x2 - srect->x1) / (float) (drect->x2 - drect->x1);
2795     yrel = (float) (srect->y2 - srect->y1) / (float) (drect->y2 - drect->y1);
2796
2797     if( (xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) {
2798         FIXME("Doing a pixel by pixel copy from the framebuffer to a texture, expect major performance issues\n");
2799
2800         if(Filter != WINED3DTEXF_NONE && Filter != WINED3DTEXF_POINT) {
2801             ERR("Texture filtering not supported in direct blit\n");
2802         }
2803     } else if((Filter != WINED3DTEXF_NONE && Filter != WINED3DTEXF_POINT) && ((yrel - 1.0 < -eps) || (yrel - 1.0 > eps))) {
2804         ERR("Texture filtering not supported in direct blit\n");
2805     }
2806
2807     if(upsidedown &&
2808        !((xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) &&
2809        !((yrel - 1.0 < -eps) || (yrel - 1.0 > eps))) {
2810         /* Upside down copy without stretching is nice, one glCopyTexSubImage call will do */
2811
2812         glCopyTexSubImage2D(This->glDescription.target,
2813                             This->glDescription.level,
2814                             drect->x1, drect->y1, /* xoffset, yoffset */
2815                             srect->x1, Src->currentDesc.Height - srect->y2,
2816                             drect->x2 - drect->x1, drect->y2 - drect->y1);
2817     } else {
2818         UINT yoffset = Src->currentDesc.Height - srect->y1 + drect->y1 - 1;
2819         /* I have to process this row by row to swap the image,
2820          * otherwise it would be upside down, so stretching in y direction
2821          * doesn't cost extra time
2822          *
2823          * However, stretching in x direction can be avoided if not necessary
2824          */
2825         for(row = drect->y1; row < drect->y2; row++) {
2826             if( (xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) {
2827                 /* Well, that stuff works, but it's very slow.
2828                  * find a better way instead
2829                  */
2830                 UINT col;
2831
2832                 for(col = drect->x1; col < drect->x2; col++) {
2833                     glCopyTexSubImage2D(This->glDescription.target,
2834                                         This->glDescription.level,
2835                                         drect->x1 + col, row, /* xoffset, yoffset */
2836                                         srect->x1 + col * xrel, yoffset - (int) (row * yrel),
2837                                         1, 1);
2838                 }
2839             } else {
2840                 glCopyTexSubImage2D(This->glDescription.target,
2841                                     This->glDescription.level,
2842                                     drect->x1, row, /* xoffset, yoffset */
2843                                     srect->x1, yoffset - (int) (row * yrel),
2844                                     drect->x2-drect->x1, 1);
2845             }
2846         }
2847     }
2848     vcheckGLcall("glCopyTexSubImage2D");
2849
2850     /* Leave the opengl state valid for blitting */
2851     glDisable(This->glDescription.target);
2852     checkGLcall("glDisable(This->glDescription.target)");
2853
2854     LEAVE_GL();
2855 }
2856
2857 /* Uses the hardware to stretch and flip the image */
2858 static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWineD3DSurface *SrcSurface, IWineD3DSwapChainImpl *swapchain, WINED3DRECT *srect, WINED3DRECT *drect, BOOL upsidedown, WINED3DTEXTUREFILTERTYPE Filter) {
2859     GLuint src, backup = 0;
2860     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
2861     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
2862     float left, right, top, bottom; /* Texture coordinates */
2863     UINT fbwidth = Src->currentDesc.Width;
2864     UINT fbheight = Src->currentDesc.Height;
2865     GLenum drawBuffer = GL_BACK;
2866     GLenum texture_target;
2867     BOOL noBackBufferBackup;
2868
2869     TRACE("Using hwstretch blit\n");
2870     /* Activate the Proper context for reading from the source surface, set it up for blitting */
2871     ActivateContext(myDevice, SrcSurface, CTXUSAGE_BLIT);
2872     IWineD3DSurface_PreLoad((IWineD3DSurface *) This);
2873
2874     noBackBufferBackup = !swapchain && wined3d_settings.offscreen_rendering_mode == ORM_FBO;
2875     if(!noBackBufferBackup && Src->glDescription.textureName == 0) {
2876         /* Get it a description */
2877         IWineD3DSurface_PreLoad(SrcSurface);
2878     }
2879     ENTER_GL();
2880
2881     /* Try to use an aux buffer for drawing the rectangle. This way it doesn't need restoring.
2882      * This way we don't have to wait for the 2nd readback to finish to leave this function.
2883      */
2884     if(myDevice->activeContext->aux_buffers >= 2) {
2885         /* Got more than one aux buffer? Use the 2nd aux buffer */
2886         drawBuffer = GL_AUX1;
2887     } else if((swapchain || myDevice->offscreenBuffer == GL_BACK) && myDevice->activeContext->aux_buffers >= 1) {
2888         /* Only one aux buffer, but it isn't used (Onscreen rendering, or non-aux orm)? Use it! */
2889         drawBuffer = GL_AUX0;
2890     }
2891
2892     if(noBackBufferBackup) {
2893         glGenTextures(1, &backup);
2894         checkGLcall("glGenTextures\n");
2895         glBindTexture(GL_TEXTURE_2D, backup);
2896         checkGLcall("glBindTexture(Src->glDescription.target, Src->glDescription.textureName)");
2897         texture_target = GL_TEXTURE_2D;
2898     } else {
2899         /* Backup the back buffer and copy the source buffer into a texture to draw an upside down stretched quad. If
2900          * we are reading from the back buffer, the backup can be used as source texture
2901          */
2902         texture_target = Src->glDescription.target;
2903         glBindTexture(texture_target, Src->glDescription.textureName);
2904         checkGLcall("glBindTexture(texture_target, Src->glDescription.textureName)");
2905         glEnable(texture_target);
2906         checkGLcall("glEnable(texture_target)");
2907
2908         /* For now invalidate the texture copy of the back buffer. Drawable and sysmem copy are untouched */
2909         Src->Flags &= ~SFLAG_INTEXTURE;
2910     }
2911
2912     if(swapchain) {
2913         glReadBuffer(surface_get_gl_buffer(SrcSurface, (IWineD3DSwapChain *)swapchain));
2914     } else {
2915         TRACE("Reading from an offscreen target\n");
2916         upsidedown = !upsidedown;
2917         glReadBuffer(myDevice->offscreenBuffer);
2918     }
2919
2920     /* TODO: Only back up the part that will be overwritten */
2921     glCopyTexSubImage2D(texture_target, 0,
2922                         0, 0 /* read offsets */,
2923                         0, 0,
2924                         fbwidth,
2925                         fbheight);
2926
2927     checkGLcall("glCopyTexSubImage2D");
2928
2929     /* No issue with overriding these - the sampler is dirty due to blit usage */
2930     glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER,
2931                     magLookup[Filter - WINED3DTEXF_NONE]);
2932     checkGLcall("glTexParameteri");
2933     glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER,
2934                     minMipLookup[Filter][WINED3DTEXF_NONE]);
2935     checkGLcall("glTexParameteri");
2936
2937     if(!swapchain || (IWineD3DSurface *) Src == swapchain->backBuffer[0]) {
2938         src = backup ? backup : Src->glDescription.textureName;
2939     } else {
2940         glReadBuffer(GL_FRONT);
2941         checkGLcall("glReadBuffer(GL_FRONT)");
2942
2943         glGenTextures(1, &src);
2944         checkGLcall("glGenTextures(1, &src)");
2945         glBindTexture(GL_TEXTURE_2D, src);
2946         checkGLcall("glBindTexture(GL_TEXTURE_2D, src)");
2947
2948         /* TODO: Only copy the part that will be read. Use srect->x1, srect->y2 as origin, but with the width watch
2949          * out for power of 2 sizes
2950          */
2951         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Src->pow2Width, Src->pow2Height, 0,
2952                     GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2953         checkGLcall("glTexImage2D");
2954         glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
2955                             0, 0 /* read offsets */,
2956                             0, 0,
2957                             fbwidth,
2958                             fbheight);
2959
2960         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2961         checkGLcall("glTexParameteri");
2962         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2963         checkGLcall("glTexParameteri");
2964
2965         glReadBuffer(GL_BACK);
2966         checkGLcall("glReadBuffer(GL_BACK)");
2967
2968         if(texture_target != GL_TEXTURE_2D) {
2969             glDisable(texture_target);
2970             glEnable(GL_TEXTURE_2D);
2971             texture_target = GL_TEXTURE_2D;
2972         }
2973     }
2974     checkGLcall("glEnd and previous");
2975
2976     left = srect->x1;
2977     right = srect->x2;
2978
2979     if(upsidedown) {
2980         top = Src->currentDesc.Height - srect->y1;
2981         bottom = Src->currentDesc.Height - srect->y2;
2982     } else {
2983         top = Src->currentDesc.Height - srect->y2;
2984         bottom = Src->currentDesc.Height - srect->y1;
2985     }
2986
2987     if(Src->Flags & SFLAG_NORMCOORD) {
2988         left /= Src->pow2Width;
2989         right /= Src->pow2Width;
2990         top /= Src->pow2Height;
2991         bottom /= Src->pow2Height;
2992     }
2993
2994     /* draw the source texture stretched and upside down. The correct surface is bound already */
2995     glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP);
2996     glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP);
2997
2998     glDrawBuffer(drawBuffer);
2999     glReadBuffer(drawBuffer);
3000
3001     glBegin(GL_QUADS);
3002         /* bottom left */
3003         glTexCoord2f(left, bottom);
3004         glVertex2i(0, fbheight);
3005
3006         /* top left */
3007         glTexCoord2f(left, top);
3008         glVertex2i(0, fbheight - drect->y2 - drect->y1);
3009
3010         /* top right */
3011         glTexCoord2f(right, top);
3012         glVertex2i(drect->x2 - drect->x1, fbheight - drect->y2 - drect->y1);
3013
3014         /* bottom right */
3015         glTexCoord2f(right, bottom);
3016         glVertex2i(drect->x2 - drect->x1, fbheight);
3017     glEnd();
3018     checkGLcall("glEnd and previous");
3019
3020     if(texture_target != This->glDescription.target) {
3021         glDisable(texture_target);
3022         glEnable(This->glDescription.target);
3023         texture_target = This->glDescription.target;
3024     }
3025
3026     /* Now read the stretched and upside down image into the destination texture */
3027     glBindTexture(texture_target, This->glDescription.textureName);
3028     checkGLcall("glBindTexture");
3029     glCopyTexSubImage2D(texture_target,
3030                         0,
3031                         drect->x1, drect->y1, /* xoffset, yoffset */
3032                         0, 0, /* We blitted the image to the origin */
3033                         drect->x2 - drect->x1, drect->y2 - drect->y1);
3034     checkGLcall("glCopyTexSubImage2D");
3035
3036     if(drawBuffer == GL_BACK) {
3037         /* Write the back buffer backup back */
3038         if(backup) {
3039             if(texture_target != GL_TEXTURE_2D) {
3040                 glDisable(texture_target);
3041                 glEnable(GL_TEXTURE_2D);
3042                 texture_target = GL_TEXTURE_2D;
3043             }
3044             glBindTexture(GL_TEXTURE_2D, backup);
3045             checkGLcall("glBindTexture(GL_TEXTURE_2D, backup)");
3046         } else {
3047             if(texture_target != Src->glDescription.target) {
3048                 glDisable(texture_target);
3049                 glEnable(Src->glDescription.target);
3050                 texture_target = Src->glDescription.target;
3051             }
3052             glBindTexture(Src->glDescription.target, Src->glDescription.textureName);
3053             checkGLcall("glBindTexture(Src->glDescription.target, Src->glDescription.textureName)");
3054         }
3055
3056         glBegin(GL_QUADS);
3057             /* top left */
3058             glTexCoord2f(0.0, (float) fbheight / (float) Src->pow2Height);
3059             glVertex2i(0, 0);
3060
3061             /* bottom left */
3062             glTexCoord2f(0.0, 0.0);
3063             glVertex2i(0, fbheight);
3064
3065             /* bottom right */
3066             glTexCoord2f((float) fbwidth / (float) Src->pow2Width, 0.0);
3067             glVertex2i(fbwidth, Src->currentDesc.Height);
3068
3069             /* top right */
3070             glTexCoord2f((float) fbwidth / (float) Src->pow2Width, (float) fbheight / (float) Src->pow2Height);
3071             glVertex2i(fbwidth, 0);
3072         glEnd();
3073     } else {
3074         /* Restore the old draw buffer */
3075         glDrawBuffer(GL_BACK);
3076     }
3077     glDisable(texture_target);
3078     checkGLcall("glDisable(texture_target)");
3079
3080     /* Cleanup */
3081     if(src != Src->glDescription.textureName && src != backup) {
3082         glDeleteTextures(1, &src);
3083         checkGLcall("glDeleteTextures(1, &src)");
3084     }
3085     if(backup) {
3086         glDeleteTextures(1, &backup);
3087         checkGLcall("glDeleteTextures(1, &backup)");
3088     }
3089
3090     LEAVE_GL();
3091 }
3092
3093 /* Not called from the VTable */
3094 static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, WINEDDBLTFX *DDBltFx, WINED3DTEXTUREFILTERTYPE Filter) {
3095     WINED3DRECT rect;
3096     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
3097     IWineD3DSwapChainImpl *srcSwapchain = NULL, *dstSwapchain = NULL;
3098     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
3099
3100     TRACE("(%p)->(%p,%p,%p,%08x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
3101
3102     /* Get the swapchain. One of the surfaces has to be a primary surface */
3103     if(This->resource.pool == WINED3DPOOL_SYSTEMMEM) {
3104         WARN("Destination is in sysmem, rejecting gl blt\n");
3105         return WINED3DERR_INVALIDCALL;
3106     }
3107     IWineD3DSurface_GetContainer( (IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&dstSwapchain);
3108     if(dstSwapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) dstSwapchain);
3109     if(Src) {
3110         if(Src->resource.pool == WINED3DPOOL_SYSTEMMEM) {
3111             WARN("Src is in sysmem, rejecting gl blt\n");
3112             return WINED3DERR_INVALIDCALL;
3113         }
3114         IWineD3DSurface_GetContainer( (IWineD3DSurface *) Src, &IID_IWineD3DSwapChain, (void **)&srcSwapchain);
3115         if(srcSwapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) srcSwapchain);
3116     }
3117
3118     /* Early sort out of cases where no render target is used */
3119     if(!dstSwapchain && !srcSwapchain &&
3120         SrcSurface != myDevice->render_targets[0] && This != (IWineD3DSurfaceImpl *) myDevice->render_targets[0]) {
3121         TRACE("No surface is render target, not using hardware blit. Src = %p, dst = %p\n", Src, This);
3122         return WINED3DERR_INVALIDCALL;
3123     }
3124
3125     /* No destination color keying supported */
3126     if(Flags & (WINEDDBLT_KEYDEST | WINEDDBLT_KEYDESTOVERRIDE)) {
3127         /* Can we support that with glBlendFunc if blitting to the frame buffer? */
3128         TRACE("Destination color key not supported in accelerated Blit, falling back to software\n");
3129         return WINED3DERR_INVALIDCALL;
3130     }
3131
3132     if (DestRect) {
3133         rect.x1 = DestRect->left;
3134         rect.y1 = DestRect->top;
3135         rect.x2 = DestRect->right;
3136         rect.y2 = DestRect->bottom;
3137     } else {
3138         rect.x1 = 0;
3139         rect.y1 = 0;
3140         rect.x2 = This->currentDesc.Width;
3141         rect.y2 = This->currentDesc.Height;
3142     }
3143
3144     /* The only case where both surfaces on a swapchain are supported is a back buffer -> front buffer blit on the same swapchain */
3145     if(dstSwapchain && dstSwapchain == srcSwapchain && dstSwapchain->backBuffer &&
3146        ((IWineD3DSurface *) This == dstSwapchain->frontBuffer) && SrcSurface == dstSwapchain->backBuffer[0]) {
3147         /* Half-life does a Blt from the back buffer to the front buffer,
3148          * Full surface size, no flags... Use present instead
3149          *
3150          * This path will only be entered for d3d7 and ddraw apps, because d3d8/9 offer no way to blit TO the front buffer
3151          */
3152
3153         /* Check rects - IWineD3DDevice_Present doesn't handle them */
3154         while(1)
3155         {
3156             RECT mySrcRect;
3157             TRACE("Looking if a Present can be done...\n");
3158             /* Source Rectangle must be full surface */
3159             if( SrcRect ) {
3160                 if(SrcRect->left != 0 || SrcRect->top != 0 ||
3161                    SrcRect->right != Src->currentDesc.Width || SrcRect->bottom != Src->currentDesc.Height) {
3162                     TRACE("No, Source rectangle doesn't match\n");
3163                     break;
3164                 }
3165             }
3166             mySrcRect.left = 0;
3167             mySrcRect.top = 0;
3168             mySrcRect.right = Src->currentDesc.Width;
3169             mySrcRect.bottom = Src->currentDesc.Height;
3170
3171             /* No stretching may occur */
3172             if(mySrcRect.right != rect.x2 - rect.x1 ||
3173                mySrcRect.bottom != rect.y2 - rect.y1) {
3174                 TRACE("No, stretching is done\n");
3175                 break;
3176             }
3177
3178             /* Destination must be full surface or match the clipping rectangle */
3179             if(This->clipper && ((IWineD3DClipperImpl *) This->clipper)->hWnd)
3180             {
3181                 RECT cliprect;
3182                 POINT pos[2];
3183                 GetClientRect(((IWineD3DClipperImpl *) This->clipper)->hWnd, &cliprect);
3184                 pos[0].x = rect.x1;
3185                 pos[0].y = rect.y1;
3186                 pos[1].x = rect.x2;
3187                 pos[1].y = rect.y2;
3188                 MapWindowPoints(GetDesktopWindow(), ((IWineD3DClipperImpl *) This->clipper)->hWnd,
3189                                 pos, 2);
3190
3191                 if(pos[0].x != cliprect.left  || pos[0].y != cliprect.top   ||
3192                    pos[1].x != cliprect.right || pos[1].y != cliprect.bottom)
3193                 {
3194                     TRACE("No, dest rectangle doesn't match(clipper)\n");
3195                     TRACE("Clip rect at (%d,%d)-(%d,%d)\n", cliprect.left, cliprect.top, cliprect.right, cliprect.bottom);
3196                     TRACE("Blt dest: (%d,%d)-(%d,%d)\n", rect.x1, rect.y1, rect.x2, rect.y2);
3197                     break;
3198                 }
3199             }
3200             else
3201             {
3202                 if(rect.x1 != 0 || rect.y1 != 0 ||
3203                    rect.x2 != This->currentDesc.Width || rect.y2 != This->currentDesc.Height) {
3204                     TRACE("No, dest rectangle doesn't match(surface size)\n");
3205                     break;
3206                 }
3207             }
3208
3209             TRACE("Yes\n");
3210
3211             /* These flags are unimportant for the flag check, remove them */
3212             if((Flags & ~(WINEDDBLT_DONOTWAIT | WINEDDBLT_WAIT)) == 0) {
3213                 WINED3DSWAPEFFECT orig_swap = dstSwapchain->presentParms.SwapEffect;
3214
3215                 /* The idea behind this is that a glReadPixels and a glDrawPixels call
3216                     * take very long, while a flip is fast.
3217                     * This applies to Half-Life, which does such Blts every time it finished
3218                     * a frame, and to Prince of Persia 3D, which uses this to draw at least the main
3219                     * menu. This is also used by all apps when they do windowed rendering
3220                     *
3221                     * The problem is that flipping is not really the same as copying. After a
3222                     * Blt the front buffer is a copy of the back buffer, and the back buffer is
3223                     * untouched. Therefore it's necessary to override the swap effect
3224                     * and to set it back after the flip.
3225                     *
3226                     * Windowed Direct3D < 7 apps do the same. The D3D7 sdk demos are nice
3227                     * testcases.
3228                     */
3229
3230                 dstSwapchain->presentParms.SwapEffect = WINED3DSWAPEFFECT_COPY;
3231                 dstSwapchain->presentParms.PresentationInterval = WINED3DPRESENT_INTERVAL_IMMEDIATE;
3232
3233                 TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n");
3234                 IWineD3DSwapChain_Present((IWineD3DSwapChain *) dstSwapchain, NULL, NULL, 0, NULL, 0);
3235
3236                 dstSwapchain->presentParms.SwapEffect = orig_swap;
3237
3238                 return WINED3D_OK;
3239             }
3240             break;
3241         }
3242
3243         TRACE("Unsupported blit between buffers on the same swapchain\n");
3244         return WINED3DERR_INVALIDCALL;
3245     } else if(dstSwapchain && dstSwapchain == srcSwapchain) {
3246         FIXME("Implement hardware blit between two surfaces on the same swapchain\n");
3247         return WINED3DERR_INVALIDCALL;
3248     } else if(dstSwapchain && srcSwapchain) {
3249         FIXME("Implement hardware blit between two different swapchains\n");
3250         return WINED3DERR_INVALIDCALL;
3251     } else if(dstSwapchain) {
3252         if(SrcSurface == myDevice->render_targets[0]) {
3253             TRACE("Blit from active render target to a swapchain\n");
3254             /* Handled with regular texture -> swapchain blit */
3255         }
3256     } else if(srcSwapchain && This == (IWineD3DSurfaceImpl *) myDevice->render_targets[0]) {
3257         FIXME("Implement blit from a swapchain to the active render target\n");
3258         return WINED3DERR_INVALIDCALL;
3259     }
3260
3261     if((srcSwapchain || SrcSurface == myDevice->render_targets[0]) && !dstSwapchain) {
3262         /* Blit from render target to texture */
3263         WINED3DRECT srect;
3264         BOOL upsideDown, stretchx;
3265         BOOL paletteOverride = FALSE;
3266
3267         if(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) {
3268             TRACE("Color keying not supported by frame buffer to texture blit\n");
3269             return WINED3DERR_INVALIDCALL;
3270             /* Destination color key is checked above */
3271         }
3272
3273         /* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag
3274          * glCopyTexSubImage is a bit picky about the parameters we pass to it
3275          */
3276         if(SrcRect) {
3277             if(SrcRect->top < SrcRect->bottom) {
3278                 srect.y1 = SrcRect->top;
3279                 srect.y2 = SrcRect->bottom;
3280                 upsideDown = FALSE;
3281             } else {
3282                 srect.y1 = SrcRect->bottom;
3283                 srect.y2 = SrcRect->top;
3284                 upsideDown = TRUE;
3285             }
3286             srect.x1 = SrcRect->left;
3287             srect.x2 = SrcRect->right;
3288         } else {
3289             srect.x1 = 0;
3290             srect.y1 = 0;
3291             srect.x2 = Src->currentDesc.Width;
3292             srect.y2 = Src->currentDesc.Height;
3293             upsideDown = FALSE;
3294         }
3295         if(rect.x1 > rect.x2) {
3296             UINT tmp = rect.x2;
3297             rect.x2 = rect.x1;
3298             rect.x1 = tmp;
3299             upsideDown = !upsideDown;
3300         }
3301
3302         if(rect.x2 - rect.x1 != srect.x2 - srect.x1) {
3303             stretchx = TRUE;
3304         } else {
3305             stretchx = FALSE;
3306         }
3307
3308         /* When blitting from a render target a texture, the texture isn't required to have a palette.
3309          * In this case grab the palette from the render target. */
3310         if((This->resource.format == WINED3DFMT_P8) && (This->palette == NULL)) {
3311             paletteOverride = TRUE;
3312             TRACE("Source surface (%p) lacks palette, overriding palette with palette %p of destination surface (%p)\n", Src, This->palette, This);
3313             This->palette = Src->palette;
3314         }
3315
3316         /* Blt is a pretty powerful call, while glCopyTexSubImage2D is not. glCopyTexSubImage cannot
3317          * flip the image nor scale it.
3318          *
3319          * -> If the app asks for a unscaled, upside down copy, just perform one glCopyTexSubImage2D call
3320          * -> If the app wants a image width an unscaled width, copy it line per line
3321          * -> If the app wants a image that is scaled on the x axis, and the destination rectangle is smaller
3322          *    than the frame buffer, draw an upside down scaled image onto the fb, read it back and restore the
3323          *    back buffer. This is slower than reading line per line, thus not used for flipping
3324          * -> If the app wants a scaled image with a dest rect that is bigger than the fb, it has to be copied
3325          *    pixel by pixel
3326          *
3327          * If EXT_framebuffer_blit is supported that can be used instead. Note that EXT_framebuffer_blit implies
3328          * FBO support, so it doesn't really make sense to try and make it work with different offscreen rendering
3329          * backends.
3330          */
3331         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && GL_SUPPORT(EXT_FRAMEBUFFER_BLIT)) {
3332             stretch_rect_fbo((IWineD3DDevice *)myDevice, SrcSurface, &srect,
3333                     (IWineD3DSurface *)This, &rect, Filter, upsideDown);
3334         } else if((!stretchx) || rect.x2 - rect.x1 > Src->currentDesc.Width ||
3335                                     rect.y2 - rect.y1 > Src->currentDesc.Height) {
3336             TRACE("No stretching in x direction, using direct framebuffer -> texture copy\n");
3337             fb_copy_to_texture_direct(This, SrcSurface, srcSwapchain, &srect, &rect, upsideDown, Filter);
3338         } else {
3339             TRACE("Using hardware stretching to flip / stretch the texture\n");
3340             fb_copy_to_texture_hwstretch(This, SrcSurface, srcSwapchain, &srect, &rect, upsideDown, Filter);
3341         }
3342
3343         /* Clear the palette as the surface didn't have a palette attached, it would confuse GetPalette and other calls */
3344         if(paletteOverride)
3345             This->palette = NULL;
3346
3347         if(!(This->Flags & SFLAG_DONOTFREE)) {
3348             HeapFree(GetProcessHeap(), 0, This->resource.heapMemory);
3349             This->resource.allocatedMemory = NULL;
3350             This->resource.heapMemory = NULL;
3351         } else {
3352             This->Flags &= ~SFLAG_INSYSMEM;
3353         }
3354         /* The texture is now most up to date - If the surface is a render target and has a drawable, this
3355          * path is never entered
3356          */
3357         IWineD3DSurface_ModifyLocation((IWineD3DSurface *) This, SFLAG_INTEXTURE, TRUE);
3358
3359         return WINED3D_OK;
3360     } else if(Src) {
3361         /* Blit from offscreen surface to render target */
3362         float glTexCoord[4];
3363         DWORD oldCKeyFlags = Src->CKeyFlags;
3364         WINEDDCOLORKEY oldBltCKey = Src->SrcBltCKey;
3365         RECT SourceRectangle;
3366         BOOL paletteOverride = FALSE;
3367         GLenum buffer;
3368
3369         TRACE("Blt from surface %p to rendertarget %p\n", Src, This);
3370
3371         if(SrcRect) {
3372             SourceRectangle.left = SrcRect->left;
3373             SourceRectangle.right = SrcRect->right;
3374             SourceRectangle.top = SrcRect->top;
3375             SourceRectangle.bottom = SrcRect->bottom;
3376         } else {
3377             SourceRectangle.left = 0;
3378             SourceRectangle.right = Src->currentDesc.Width;
3379             SourceRectangle.top = 0;
3380             SourceRectangle.bottom = Src->currentDesc.Height;
3381         }
3382
3383         /* When blitting from an offscreen surface to a rendertarget, the source
3384          * surface is not required to have a palette. Our rendering / conversion
3385          * code further down the road retrieves the palette from the surface, so
3386          * it must have a palette set. */
3387         if((Src->resource.format == WINED3DFMT_P8) && (Src->palette == NULL)) {
3388             paletteOverride = TRUE;
3389             TRACE("Source surface (%p) lacks palette, overriding palette with palette %p of destination surface (%p)\n", Src, This->palette, This);
3390             Src->palette = This->palette;
3391         }
3392
3393         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && GL_SUPPORT(EXT_FRAMEBUFFER_BLIT) &&
3394             (Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) == 0) {
3395             TRACE("Using stretch_rect_fbo\n");
3396             /* The source is always a texture, but never the currently active render target, and the texture
3397              * contents are never upside down
3398              */
3399             stretch_rect_fbo((IWineD3DDevice *)myDevice, SrcSurface, (WINED3DRECT *) &SourceRectangle,
3400                               (IWineD3DSurface *)This, &rect, Filter, FALSE);
3401
3402             /* Clear the palette as the surface didn't have a palette attached, it would confuse GetPalette and other calls */
3403             if(paletteOverride)
3404                 Src->palette = NULL;
3405             return WINED3D_OK;
3406         }
3407
3408         if(!CalculateTexRect(Src, &SourceRectangle, glTexCoord)) {
3409             /* Fall back to software */
3410             WARN("(%p) Source texture area (%d,%d)-(%d,%d) is too big\n", Src,
3411                     SourceRectangle.left, SourceRectangle.top,
3412                     SourceRectangle.right, SourceRectangle.bottom);
3413             return WINED3DERR_INVALIDCALL;
3414         }
3415
3416         /* Color keying: Check if we have to do a color keyed blt,
3417          * and if not check if a color key is activated.
3418          *
3419          * Just modify the color keying parameters in the surface and restore them afterwards
3420          * The surface keeps track of the color key last used to load the opengl surface.
3421          * PreLoad will catch the change to the flags and color key and reload if necessary.
3422          */
3423         if(Flags & WINEDDBLT_KEYSRC) {
3424             /* Use color key from surface */
3425         } else if(Flags & WINEDDBLT_KEYSRCOVERRIDE) {
3426             /* Use color key from DDBltFx */
3427             Src->CKeyFlags |= WINEDDSD_CKSRCBLT;
3428             Src->SrcBltCKey = DDBltFx->ddckSrcColorkey;
3429         } else {
3430             /* Do not use color key */
3431             Src->CKeyFlags &= ~WINEDDSD_CKSRCBLT;
3432         }
3433
3434         /* Now load the surface */
3435         IWineD3DSurface_PreLoad((IWineD3DSurface *) Src);
3436
3437
3438         /* Activate the destination context, set it up for blitting */
3439         ActivateContext(myDevice, (IWineD3DSurface *) This, CTXUSAGE_BLIT);
3440
3441         if(!dstSwapchain) {
3442             TRACE("Drawing to offscreen buffer\n");
3443             buffer = myDevice->offscreenBuffer;
3444         } else {
3445             buffer = surface_get_gl_buffer((IWineD3DSurface *)This, (IWineD3DSwapChain *)dstSwapchain);
3446
3447             /* Front buffer coordinates are screen coordinates, while OpenGL coordinates are
3448              * window relative. Also beware of the origin difference(top left vs bottom left).
3449              * Also beware that the front buffer's surface size is screen width x screen height,
3450              * whereas the real gl drawable size is the size of the window.
3451              */
3452             if(buffer == GL_FRONT) {
3453                 RECT windowsize;
3454                 POINT offset = {0,0};
3455                 UINT h;
3456                 ClientToScreen(dstSwapchain->win_handle, &offset);
3457                 GetClientRect(dstSwapchain->win_handle, &windowsize);
3458                 h = windowsize.bottom - windowsize.top;
3459                 rect.x1 -= offset.x; rect.x2 -=offset.x;
3460                 rect.y1 -= offset.y; rect.y2 -=offset.y;
3461                 rect.y1 += This->currentDesc.Height - h; rect.y2 += This->currentDesc.Height - h;
3462             }
3463             TRACE("Drawing to %#x buffer\n", buffer);
3464         }
3465
3466         ENTER_GL();
3467         glDrawBuffer(buffer);
3468         checkGLcall("glDrawBuffer");
3469
3470         myDevice->blitter->set_shader((IWineD3DDevice *) myDevice, Src->resource.format,
3471                                        Src->glDescription.target, Src->pow2Width, Src->pow2Height);
3472
3473         /* Bind the texture */
3474         glBindTexture(Src->glDescription.target, Src->glDescription.textureName);
3475         checkGLcall("glBindTexture");
3476
3477         /* Filtering for StretchRect */
3478         glTexParameteri(Src->glDescription.target, GL_TEXTURE_MAG_FILTER,
3479                         magLookup[Filter - WINED3DTEXF_NONE]);
3480         checkGLcall("glTexParameteri");
3481         glTexParameteri(Src->glDescription.target, GL_TEXTURE_MIN_FILTER,
3482                         minMipLookup[Filter][WINED3DTEXF_NONE]);
3483         checkGLcall("glTexParameteri");
3484         glTexParameteri(Src->glDescription.target, GL_TEXTURE_WRAP_S, GL_CLAMP);
3485         glTexParameteri(Src->glDescription.target, GL_TEXTURE_WRAP_T, GL_CLAMP);
3486         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3487         checkGLcall("glTexEnvi");
3488
3489         /* This is for color keying */
3490         if(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) {
3491             glEnable(GL_ALPHA_TEST);
3492             checkGLcall("glEnable GL_ALPHA_TEST");
3493
3494             /* When the primary render target uses P8, the alpha component contains the palette index.
3495              * Which means that the colorkey is one of the palette entries. In other cases pixels that
3496              * should be masked away have alpha set to 0. */
3497             if(primary_render_target_is_p8(myDevice))
3498                 glAlphaFunc(GL_NOTEQUAL, (float)Src->SrcBltCKey.dwColorSpaceLowValue / 256.0);
3499             else
3500                 glAlphaFunc(GL_NOTEQUAL, 0.0);
3501             checkGLcall("glAlphaFunc\n");
3502         } else {
3503             glDisable(GL_ALPHA_TEST);
3504             checkGLcall("glDisable GL_ALPHA_TEST");
3505         }
3506
3507         /* Draw a textured quad
3508          */
3509         glBegin(GL_QUADS);
3510
3511         glColor3d(1.0f, 1.0f, 1.0f);
3512         glTexCoord2f(glTexCoord[0], glTexCoord[2]);
3513         glVertex3f(rect.x1,
3514                     rect.y1,
3515                     0.0);
3516
3517         glTexCoord2f(glTexCoord[0], glTexCoord[3]);
3518         glVertex3f(rect.x1, rect.y2, 0.0);
3519
3520         glTexCoord2f(glTexCoord[1], glTexCoord[3]);
3521         glVertex3f(rect.x2,
3522                     rect.y2,
3523                     0.0);
3524
3525         glTexCoord2f(glTexCoord[1], glTexCoord[2]);
3526         glVertex3f(rect.x2,
3527                     rect.y1,
3528                     0.0);
3529         glEnd();
3530         checkGLcall("glEnd");
3531
3532         if(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) {
3533             glDisable(GL_ALPHA_TEST);
3534             checkGLcall("glDisable(GL_ALPHA_TEST)");
3535         }
3536
3537         glBindTexture(Src->glDescription.target, 0);
3538         checkGLcall("glBindTexture(Src->glDescription.target, 0)");
3539         /* Leave the opengl state valid for blitting */
3540         myDevice->blitter->unset_shader((IWineD3DDevice *) myDevice);
3541
3542         /* The draw buffer should only need to be restored if we were drawing to the front buffer, and there is a back buffer.
3543          * otherwise the context manager should choose between GL_BACK / offscreenDrawBuffer
3544          */
3545         if(dstSwapchain && This == (IWineD3DSurfaceImpl *) dstSwapchain->frontBuffer && dstSwapchain->backBuffer) {
3546             glDrawBuffer(GL_BACK);
3547             checkGLcall("glDrawBuffer");
3548         }
3549         /* Restore the color key parameters */
3550         Src->CKeyFlags = oldCKeyFlags;
3551         Src->SrcBltCKey = oldBltCKey;
3552
3553         /* Clear the palette as the surface didn't have a palette attached, it would confuse GetPalette and other calls */
3554         if(paletteOverride)
3555             Src->palette = NULL;
3556
3557         LEAVE_GL();
3558
3559         /* Flush in case the drawable is used by multiple GL contexts */
3560         if(dstSwapchain && (This == (IWineD3DSurfaceImpl *) dstSwapchain->frontBuffer || dstSwapchain->num_contexts >= 2))
3561             glFlush();
3562
3563         /* TODO: If the surface is locked often, perform the Blt in software on the memory instead */
3564         /* The surface is now in the drawable. On onscreen surfaces or without fbos the texture
3565          * is outdated now
3566          */
3567         IWineD3DSurface_ModifyLocation((IWineD3DSurface *) This, SFLAG_INDRAWABLE, TRUE);
3568         /* TODO: This should be moved to ModifyLocation() */
3569         if(!(dstSwapchain || wined3d_settings.offscreen_rendering_mode != ORM_FBO)) {
3570             This->Flags |= SFLAG_INTEXTURE;
3571         }
3572
3573         return WINED3D_OK;
3574     } else {
3575         /* Source-Less Blit to render target */
3576         if (Flags & WINEDDBLT_COLORFILL) {
3577             /* This is easy to handle for the D3D Device... */
3578             DWORD color;
3579
3580             TRACE("Colorfill\n");
3581
3582             /* This == (IWineD3DSurfaceImpl *) myDevice->render_targets[0] || dstSwapchain
3583                 must be true if we are here */
3584             if (This != (IWineD3DSurfaceImpl *) myDevice->render_targets[0] &&
3585                     !(This == (IWineD3DSurfaceImpl*) dstSwapchain->frontBuffer ||
3586                       (dstSwapchain->backBuffer && This == (IWineD3DSurfaceImpl*) dstSwapchain->backBuffer[0]))) {
3587                 TRACE("Surface is higher back buffer, falling back to software\n");
3588                 return WINED3DERR_INVALIDCALL;
3589             }
3590
3591             /* The color as given in the Blt function is in the format of the frame-buffer...
3592              * 'clear' expect it in ARGB format => we need to do some conversion :-)
3593              */
3594             if (This->resource.format == WINED3DFMT_P8) {
3595                 DWORD alpha;
3596
3597                 if (primary_render_target_is_p8(myDevice)) alpha = DDBltFx->u5.dwFillColor << 24;
3598                 else alpha = 0xFF000000;
3599
3600                 if (This->palette) {
3601                     color = (alpha |
3602                             (This->palette->palents[DDBltFx->u5.dwFillColor].peRed << 16) |
3603                             (This->palette->palents[DDBltFx->u5.dwFillColor].peGreen << 8) |
3604                             (This->palette->palents[DDBltFx->u5.dwFillColor].peBlue));
3605                 } else {
3606                     color = alpha;
3607                 }
3608             }
3609             else if (This->resource.format == WINED3DFMT_R5G6B5) {
3610                 if (DDBltFx->u5.dwFillColor == 0xFFFF) {
3611                     color = 0xFFFFFFFF;
3612                 } else {
3613                     color = ((0xFF000000) |
3614                             ((DDBltFx->u5.dwFillColor & 0xF800) << 8) |
3615                             ((DDBltFx->u5.dwFillColor & 0x07E0) << 5) |
3616                             ((DDBltFx->u5.dwFillColor & 0x001F) << 3));
3617                 }
3618             }
3619             else if ((This->resource.format == WINED3DFMT_R8G8B8) ||
3620                     (This->resource.format == WINED3DFMT_X8R8G8B8) ) {
3621                 color = 0xFF000000 | DDBltFx->u5.dwFillColor;
3622             }
3623             else if (This->resource.format == WINED3DFMT_A8R8G8B8) {
3624                 color = DDBltFx->u5.dwFillColor;
3625             }
3626             else {
3627                 ERR("Wrong surface type for BLT override(Format doesn't match) !\n");
3628                 return WINED3DERR_INVALIDCALL;
3629             }
3630
3631             TRACE("(%p) executing Render Target override, color = %x\n", This, color);
3632             IWineD3DDeviceImpl_ClearSurface(myDevice, This,
3633                                             1, /* Number of rectangles */
3634                                             &rect, WINED3DCLEAR_TARGET, color,
3635                                             0.0 /* Z */,
3636                                             0 /* Stencil */);
3637             return WINED3D_OK;
3638         }
3639     }
3640
3641     /* Default: Fall back to the generic blt. Not an error, a TRACE is enough */
3642     TRACE("Didn't find any usable render target setup for hw blit, falling back to software\n");
3643     return WINED3DERR_INVALIDCALL;
3644 }
3645
3646 static HRESULT WINAPI IWineD3DSurfaceImpl_BltZ(IWineD3DSurfaceImpl *This, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, WINEDDBLTFX *DDBltFx)
3647 {
3648     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
3649     float depth;
3650
3651     if (Flags & WINEDDBLT_DEPTHFILL) {
3652         switch(This->resource.format) {
3653             case WINED3DFMT_D16:
3654                 depth = (float) DDBltFx->u5.dwFillDepth / (float) 0x0000ffff;
3655                 break;
3656             case WINED3DFMT_D15S1:
3657                 depth = (float) DDBltFx->u5.dwFillDepth / (float) 0x0000fffe;
3658                 break;
3659             case WINED3DFMT_D24S8:
3660             case WINED3DFMT_D24X8:
3661                 depth = (float) DDBltFx->u5.dwFillDepth / (float) 0x00ffffff;
3662                 break;
3663             case WINED3DFMT_D32:
3664                 depth = (float) DDBltFx->u5.dwFillDepth / (float) 0xffffffff;
3665                 break;
3666             default:
3667                 depth = 0.0;
3668                 ERR("Unexpected format for depth fill: %s\n", debug_d3dformat(This->resource.format));
3669         }
3670
3671         return IWineD3DDevice_Clear((IWineD3DDevice *) myDevice,
3672                                     DestRect == NULL ? 0 : 1,
3673                                     (WINED3DRECT *) DestRect,
3674                                     WINED3DCLEAR_ZBUFFER,
3675                                     0x00000000,
3676                                     depth,
3677                                     0x00000000);
3678     }
3679
3680     FIXME("(%p): Unsupp depthstencil blit\n", This);
3681     return WINED3DERR_INVALIDCALL;
3682 }
3683
3684 static HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, WINEDDBLTFX *DDBltFx, WINED3DTEXTUREFILTERTYPE Filter) {
3685     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
3686     IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
3687     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
3688     TRACE("(%p)->(%p,%p,%p,%x,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
3689     TRACE("(%p): Usage is %s\n", This, debug_d3dusage(This->resource.usage));
3690
3691     if ( (This->Flags & SFLAG_LOCKED) || ((Src != NULL) && (Src->Flags & SFLAG_LOCKED)))
3692     {
3693         WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
3694         return WINEDDERR_SURFACEBUSY;
3695     }
3696
3697     /* Accessing the depth stencil is supposed to fail between a BeginScene and EndScene pair,
3698      * except depth blits, which seem to work
3699      */
3700     if(iface == myDevice->stencilBufferTarget || (SrcSurface && SrcSurface == myDevice->stencilBufferTarget)) {
3701         if(myDevice->inScene && !(Flags & WINEDDBLT_DEPTHFILL)) {
3702             TRACE("Attempt to access the depth stencil surface in a BeginScene / EndScene pair, returning WINED3DERR_INVALIDCALL\n");
3703             return WINED3DERR_INVALIDCALL;
3704         } else if(IWineD3DSurfaceImpl_BltZ(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx) == WINED3D_OK) {
3705             TRACE("Z Blit override handled the blit\n");
3706             return WINED3D_OK;
3707         }
3708     }
3709
3710     /* Special cases for RenderTargets */
3711     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
3712         ( Src && (Src->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
3713         if(IWineD3DSurfaceImpl_BltOverride(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx, Filter) == WINED3D_OK) return WINED3D_OK;
3714     }
3715
3716     /* For the rest call the X11 surface implementation.
3717      * For RenderTargets this should be implemented OpenGL accelerated in BltOverride,
3718      * other Blts are rather rare
3719      */
3720     return IWineD3DBaseSurfaceImpl_Blt(iface, DestRect, SrcSurface, SrcRect, Flags, DDBltFx, Filter);
3721 }
3722
3723 HRESULT WINAPI IWineD3DSurfaceImpl_BltFast(IWineD3DSurface *iface, DWORD dstx, DWORD dsty, IWineD3DSurface *Source, RECT *rsrc, DWORD trans) {
3724     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3725     IWineD3DSurfaceImpl *srcImpl = (IWineD3DSurfaceImpl *) Source;
3726     IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
3727     TRACE("(%p)->(%d, %d, %p, %p, %08x\n", iface, dstx, dsty, Source, rsrc, trans);
3728
3729     if ( (This->Flags & SFLAG_LOCKED) || ((srcImpl != NULL) && (srcImpl->Flags & SFLAG_LOCKED)))
3730     {
3731         WARN(" Surface is busy, returning DDERR_SURFACEBUSY\n");
3732         return WINEDDERR_SURFACEBUSY;
3733     }
3734
3735     if(myDevice->inScene &&
3736        (iface == myDevice->stencilBufferTarget ||
3737        (Source && Source == myDevice->stencilBufferTarget))) {
3738         TRACE("Attempt to access the depth stencil surface in a BeginScene / EndScene pair, returning WINED3DERR_INVALIDCALL\n");
3739         return WINED3DERR_INVALIDCALL;
3740     }
3741
3742     /* Special cases for RenderTargets */
3743     if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
3744         ( srcImpl && (srcImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
3745
3746         RECT SrcRect, DstRect;
3747         DWORD Flags=0;
3748
3749         if(rsrc) {
3750             SrcRect.left = rsrc->left;
3751             SrcRect.top= rsrc->top;
3752             SrcRect.bottom = rsrc->bottom;
3753             SrcRect.right = rsrc->right;
3754         } else {
3755             SrcRect.left = 0;
3756             SrcRect.top = 0;
3757             SrcRect.right = srcImpl->currentDesc.Width;
3758             SrcRect.bottom = srcImpl->currentDesc.Height;
3759         }
3760
3761         DstRect.left = dstx;
3762         DstRect.top=dsty;
3763         DstRect.right = dstx + SrcRect.right - SrcRect.left;
3764         DstRect.bottom = dsty + SrcRect.bottom - SrcRect.top;
3765
3766         /* Convert BltFast flags into Btl ones because it is called from SurfaceImpl_Blt as well */
3767         if(trans & WINEDDBLTFAST_SRCCOLORKEY)
3768             Flags |= WINEDDBLT_KEYSRC;
3769         if(trans & WINEDDBLTFAST_DESTCOLORKEY)
3770             Flags |= WINEDDBLT_KEYDEST;
3771         if(trans & WINEDDBLTFAST_WAIT)
3772             Flags |= WINEDDBLT_WAIT;
3773         if(trans & WINEDDBLTFAST_DONOTWAIT)
3774             Flags |= WINEDDBLT_DONOTWAIT;
3775
3776         if(IWineD3DSurfaceImpl_BltOverride(This, &DstRect, Source, &SrcRect, Flags, NULL, WINED3DTEXF_POINT) == WINED3D_OK) return WINED3D_OK;
3777     }
3778
3779
3780     return IWineD3DBaseSurfaceImpl_BltFast(iface, dstx, dsty, Source, rsrc, trans);
3781 }
3782
3783 HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface) {
3784     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3785     RGBQUAD col[256];
3786     IWineD3DPaletteImpl *pal = This->palette;
3787     unsigned int n;
3788     TRACE("(%p)\n", This);
3789
3790     if (!pal) return WINED3D_OK;
3791
3792     if(This->resource.format == WINED3DFMT_P8 ||
3793        This->resource.format == WINED3DFMT_A8P8)
3794     {
3795         int bpp;
3796         GLenum format, internal, type;
3797         CONVERT_TYPES convert;
3798
3799         /* Check if we are using a RTL mode which uses texturing for uploads */
3800         BOOL use_texture = (wined3d_settings.rendertargetlock_mode == RTL_READTEX || wined3d_settings.rendertargetlock_mode == RTL_TEXTEX);
3801
3802         /* Check if we have hardware palette conversion if we have convert is set to NO_CONVERSION */
3803         d3dfmt_get_conv(This, TRUE, use_texture, &format, &internal, &type, &convert, &bpp, This->srgb);
3804
3805         if((This->resource.usage & WINED3DUSAGE_RENDERTARGET) && (convert == NO_CONVERSION))
3806         {
3807             /* Make sure the texture is up to date. This call doesn't do anything if the texture is already up to date. */
3808             IWineD3DSurface_LoadLocation(iface, SFLAG_INTEXTURE, NULL);
3809
3810             /* We want to force a palette refresh, so mark the drawable as not being up to date */
3811             IWineD3DSurface_ModifyLocation(iface, SFLAG_INDRAWABLE, FALSE);
3812
3813             /* Re-upload the palette */
3814             d3dfmt_p8_upload_palette(iface, convert);
3815         } else {
3816             if(!(This->Flags & SFLAG_INSYSMEM)) {
3817                 TRACE("Palette changed with surface that does not have an up to date system memory copy\n");
3818                 IWineD3DSurface_LoadLocation(iface, SFLAG_INSYSMEM, NULL);
3819             }
3820             TRACE("Dirtifying surface\n");
3821             IWineD3DSurface_ModifyLocation(iface, SFLAG_INSYSMEM, TRUE);
3822         }
3823     }
3824
3825     if(This->Flags & SFLAG_DIBSECTION) {
3826         TRACE("(%p): Updating the hdc's palette\n", This);
3827         for (n=0; n<256; n++) {
3828             col[n].rgbRed   = pal->palents[n].peRed;
3829             col[n].rgbGreen = pal->palents[n].peGreen;
3830             col[n].rgbBlue  = pal->palents[n].peBlue;
3831             col[n].rgbReserved = 0;
3832         }
3833         SetDIBColorTable(This->hDC, 0, 256, col);
3834     }
3835
3836     /* Propagate the changes to the drawable when we have a palette. */
3837     if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
3838         IWineD3DSurface_LoadLocation(iface, SFLAG_INDRAWABLE, NULL);
3839
3840     return WINED3D_OK;
3841 }
3842
3843 static HRESULT WINAPI IWineD3DSurfaceImpl_PrivateSetup(IWineD3DSurface *iface) {
3844     /** Check against the maximum texture sizes supported by the video card **/
3845     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
3846     unsigned int pow2Width, pow2Height;
3847     const GlPixelFormatDesc *glDesc;
3848
3849     getFormatDescEntry(This->resource.format, &GLINFO_LOCATION, &glDesc);
3850     /* Setup some glformat defaults */
3851     This->glDescription.glFormat         = glDesc->glFormat;
3852     This->glDescription.glFormatInternal = glDesc->glInternal;
3853     This->glDescription.glType           = glDesc->glType;
3854
3855     This->glDescription.textureName      = 0;
3856     This->glDescription.target           = GL_TEXTURE_2D;
3857
3858     /* Non-power2 support */
3859     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO) || GL_SUPPORT(WINE_NORMALIZED_TEXRECT)) {
3860         pow2Width = This->currentDesc.Width;
3861         pow2Height = This->currentDesc.Height;
3862     } else {
3863         /* Find the nearest pow2 match */
3864         pow2Width = pow2Height = 1;
3865         while (pow2Width < This->currentDesc.Width) pow2Width <<= 1;
3866         while (pow2Height < This->currentDesc.Height) pow2Height <<= 1;
3867     }
3868     This->pow2Width  = pow2Width;
3869     This->pow2Height = pow2Height;
3870
3871     if (pow2Width > This->currentDesc.Width || pow2Height > This->currentDesc.Height) {
3872         WINED3DFORMAT Format = This->resource.format;
3873         /** TODO: add support for non power two compressed textures **/
3874         if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
3875             || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5
3876             || This->resource.format == WINED3DFMT_ATI2N) {
3877             FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
3878                   This, This->currentDesc.Width, This->currentDesc.Height);
3879             return WINED3DERR_NOTAVAILABLE;
3880         }
3881     }
3882
3883     if(pow2Width != This->currentDesc.Width ||
3884        pow2Height != This->currentDesc.Height) {
3885         This->Flags |= SFLAG_NONPOW2;
3886     }
3887
3888     TRACE("%p\n", This);
3889     if ((This->pow2Width > GL_LIMITS(texture_size) || This->pow2Height > GL_LIMITS(texture_size)) && !(This->resource.usage & (WINED3DUSAGE_RENDERTARGET | WINED3DUSAGE_DEPTHSTENCIL))) {
3890         /* one of three options
3891         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)
3892         2: Set the texture to the maximum size (bad idea)
3893         3:    WARN and return WINED3DERR_NOTAVAILABLE;
3894         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.
3895         */
3896         WARN("(%p) Creating an oversized surface\n", This);
3897         This->Flags |= SFLAG_OVERSIZE;
3898
3899         /* This will be initialized on the first blt */
3900         This->glRect.left = 0;
3901         This->glRect.top = 0;
3902         This->glRect.right = 0;
3903         This->glRect.bottom = 0;
3904     } else {
3905         /* Check this after the oversize check - do not make an oversized surface a texture_rectangle one.
3906            Second also don't use ARB_TEXTURE_RECTANGLE in case the surface format is P8 and EXT_PALETTED_TEXTURE
3907            is used in combination with texture uploads (RTL_READTEX/RTL_TEXTEX). The reason is that EXT_PALETTED_TEXTURE
3908            doesn't work in combination with ARB_TEXTURE_RECTANGLE.
3909         */
3910         if(This->Flags & SFLAG_NONPOW2 && GL_SUPPORT(ARB_TEXTURE_RECTANGLE) &&
3911            !((This->resource.format == WINED3DFMT_P8) && GL_SUPPORT(EXT_PALETTED_TEXTURE) && (wined3d_settings.rendertargetlock_mode == RTL_READTEX || wined3d_settings.rendertargetlock_mode == RTL_TEXTEX)))
3912         {
3913             This->glDescription.target = GL_TEXTURE_RECTANGLE_ARB;
3914             This->pow2Width  = This->currentDesc.Width;
3915             This->pow2Height = This->currentDesc.Height;
3916             This->Flags &= ~(SFLAG_NONPOW2 | SFLAG_NORMCOORD);
3917         }
3918
3919         /* No oversize, gl rect is the full texture size */
3920         This->Flags &= ~SFLAG_OVERSIZE;
3921         This->glRect.left = 0;
3922         This->glRect.top = 0;
3923         This->glRect.right = This->pow2Width;
3924         This->glRect.bottom = This->pow2Height;
3925     }
3926
3927     if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
3928         switch(wined3d_settings.offscreen_rendering_mode) {
3929             case ORM_FBO:        This->get_drawable_size = get_drawable_size_fbo;        break;
3930             case ORM_PBUFFER:    This->get_drawable_size = get_drawable_size_pbuffer;    break;
3931             case ORM_BACKBUFFER: This->get_drawable_size = get_drawable_size_backbuffer; break;
3932         }
3933     }
3934
3935     This->Flags |= SFLAG_INSYSMEM;
3936
3937     return WINED3D_OK;
3938 }
3939
3940 void surface_modify_ds_location(IWineD3DSurface *iface, DWORD location) {
3941     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
3942
3943     TRACE("(%p) New location %#x\n", This, location);
3944
3945     if (location & ~SFLAG_DS_LOCATIONS) {
3946         FIXME("(%p) Invalid location (%#x) specified\n", This, location);
3947     }
3948
3949     This->Flags &= ~SFLAG_DS_LOCATIONS;
3950     This->Flags |= location;
3951 }
3952
3953 void surface_load_ds_location(IWineD3DSurface *iface, DWORD location) {
3954     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
3955     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
3956
3957     TRACE("(%p) New location %#x\n", This, location);
3958
3959     /* TODO: Make this work for modes other than FBO */
3960     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return;
3961
3962     if (This->Flags & location) {
3963         TRACE("(%p) Location (%#x) is already up to date\n", This, location);
3964         return;
3965     }
3966
3967     if (This->current_renderbuffer) {
3968         FIXME("(%p) Not supported with fixed up depth stencil\n", This);
3969         return;
3970     }
3971
3972     if (location == SFLAG_DS_OFFSCREEN) {
3973         if (This->Flags & SFLAG_DS_ONSCREEN) {
3974             GLint old_binding = 0;
3975
3976             TRACE("(%p) Copying onscreen depth buffer to depth texture\n", This);
3977
3978             ENTER_GL();
3979
3980             if (!device->depth_blt_texture) {
3981                 glGenTextures(1, &device->depth_blt_texture);
3982             }
3983
3984             /* Note that we use depth_blt here as well, rather than glCopyTexImage2D
3985              * directly on the FBO texture. That's because we need to flip. */
3986             GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
3987             glGetIntegerv(GL_TEXTURE_BINDING_2D, &old_binding);
3988             glBindTexture(GL_TEXTURE_2D, device->depth_blt_texture);
3989             glCopyTexImage2D(This->glDescription.target,
3990                     This->glDescription.level,
3991                     This->glDescription.glFormatInternal,
3992                     0,
3993                     0,
3994                     This->currentDesc.Width,
3995                     This->currentDesc.Height,
3996                     0);
3997             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3998             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3999             glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
4000             glBindTexture(GL_TEXTURE_2D, old_binding);
4001
4002             /* Setup the destination */
4003             if (!device->depth_blt_rb) {
4004                 GL_EXTCALL(glGenRenderbuffersEXT(1, &device->depth_blt_rb));
4005                 checkGLcall("glGenRenderbuffersEXT");
4006             }
4007             if (device->depth_blt_rb_w != This->currentDesc.Width
4008                     || device->depth_blt_rb_h != This->currentDesc.Height) {
4009                 GL_EXTCALL(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, device->depth_blt_rb));
4010                 checkGLcall("glBindRenderbufferEXT");
4011                 GL_EXTCALL(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, This->currentDesc.Width, This->currentDesc.Height));
4012                 checkGLcall("glRenderbufferStorageEXT");
4013                 device->depth_blt_rb_w = This->currentDesc.Width;
4014                 device->depth_blt_rb_h = This->currentDesc.Height;
4015             }
4016
4017             bind_fbo((IWineD3DDevice *)device, GL_FRAMEBUFFER_EXT, &device->activeContext->dst_fbo);
4018             GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, device->depth_blt_rb));
4019             checkGLcall("glFramebufferRenderbufferEXT");
4020             attach_depth_stencil_fbo(device, GL_FRAMEBUFFER_EXT, iface, FALSE);
4021
4022             /* Do the actual blit */
4023             depth_blt((IWineD3DDevice *)device, device->depth_blt_texture);
4024             checkGLcall("depth_blt");
4025
4026             if (device->render_offscreen) {
4027                 bind_fbo((IWineD3DDevice *)device, GL_FRAMEBUFFER_EXT, &device->activeContext->fbo);
4028             } else {
4029                 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
4030                 checkGLcall("glBindFramebuffer()");
4031             }
4032
4033             LEAVE_GL();
4034         } else {
4035             FIXME("No up to date depth stencil location\n");
4036         }
4037     } else if (location == SFLAG_DS_ONSCREEN) {
4038         if (This->Flags & SFLAG_DS_OFFSCREEN) {
4039             TRACE("(%p) Copying depth texture to onscreen depth buffer\n", This);
4040
4041             ENTER_GL();
4042
4043             GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
4044             checkGLcall("glBindFramebuffer()");
4045             depth_blt((IWineD3DDevice *)device, This->glDescription.textureName);
4046             checkGLcall("depth_blt");
4047
4048             if (device->render_offscreen) {
4049                 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, device->activeContext->fbo));
4050                 checkGLcall("glBindFramebuffer()");
4051             }
4052
4053             LEAVE_GL();
4054         } else {
4055             FIXME("No up to date depth stencil location\n");
4056         }
4057     } else {
4058         ERR("(%p) Invalid location (%#x) specified\n", This, location);
4059     }
4060
4061     This->Flags |= location;
4062 }
4063
4064 static void WINAPI IWineD3DSurfaceImpl_ModifyLocation(IWineD3DSurface *iface, DWORD flag, BOOL persistent) {
4065     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
4066     IWineD3DBaseTexture *texture;
4067     IWineD3DSurfaceImpl *overlay;
4068
4069     TRACE("(%p)->(%s, %s)\n", iface,
4070           flag == SFLAG_INSYSMEM ? "SFLAG_INSYSMEM" : flag == SFLAG_INDRAWABLE ? "SFLAG_INDRAWABLE" : "SFLAG_INTEXTURE",
4071           persistent ? "TRUE" : "FALSE");
4072
4073     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
4074         IWineD3DSwapChain *swapchain = NULL;
4075
4076         if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain))) {
4077             TRACE("Surface %p is an onscreen surface\n", iface);
4078
4079             IWineD3DSwapChain_Release(swapchain);
4080         } else {
4081             /* With ORM_FBO, SFLAG_INTEXTURE and SFLAG_INDRAWABLE are the same for offscreen targets. */
4082             if (flag & (SFLAG_INTEXTURE | SFLAG_INDRAWABLE)) flag |= (SFLAG_INTEXTURE | SFLAG_INDRAWABLE);
4083         }
4084     }
4085
4086     if(persistent) {
4087         if((This->Flags & SFLAG_INTEXTURE) && !(flag & SFLAG_INTEXTURE)) {
4088             if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&texture) == WINED3D_OK) {
4089                 TRACE("Passing to container\n");
4090                 IWineD3DBaseTexture_SetDirty(texture, TRUE);
4091                 IWineD3DBaseTexture_Release(texture);
4092             }
4093         }
4094         This->Flags &= ~SFLAG_LOCATIONS;
4095         This->Flags |= flag;
4096
4097         /* Redraw emulated overlays, if any */
4098         if(flag & SFLAG_INDRAWABLE && !list_empty(&This->overlays)) {
4099             LIST_FOR_EACH_ENTRY(overlay, &This->overlays, IWineD3DSurfaceImpl, overlay_entry) {
4100                 IWineD3DSurface_DrawOverlay((IWineD3DSurface *) overlay);
4101             }
4102         }
4103     } else {
4104         if((This->Flags & SFLAG_INTEXTURE) && (flag & SFLAG_INTEXTURE)) {
4105             if (IWineD3DSurface_GetContainer(iface, &IID_IWineD3DBaseTexture, (void **)&texture) == WINED3D_OK) {
4106                 TRACE("Passing to container\n");
4107                 IWineD3DBaseTexture_SetDirty(texture, TRUE);
4108                 IWineD3DBaseTexture_Release(texture);
4109             }
4110         }
4111         This->Flags &= ~flag;
4112     }
4113 }
4114
4115 struct coords {
4116     GLfloat x, y, z;
4117 };
4118
4119 static inline void surface_blt_to_drawable(IWineD3DSurfaceImpl *This, const RECT *rect_in) {
4120     struct coords coords[4];
4121     RECT rect;
4122     IWineD3DSwapChain *swapchain = NULL;
4123     IWineD3DBaseTexture *texture = NULL;
4124     HRESULT hr;
4125     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
4126
4127     if(rect_in) {
4128         rect = *rect_in;
4129     } else {
4130         rect.left = 0;
4131         rect.top = 0;
4132         rect.right = This->currentDesc.Width;
4133         rect.bottom = This->currentDesc.Height;
4134     }
4135
4136     ActivateContext(device, (IWineD3DSurface*)This, CTXUSAGE_BLIT);
4137     ENTER_GL();
4138
4139     if(This->glDescription.target == GL_TEXTURE_RECTANGLE_ARB) {
4140         glEnable(GL_TEXTURE_RECTANGLE_ARB);
4141         checkGLcall("glEnable(GL_TEXTURE_RECTANGLE_ARB)");
4142         glBindTexture(GL_TEXTURE_RECTANGLE_ARB, This->glDescription.textureName);
4143         checkGLcall("GL_TEXTURE_RECTANGLE_ARB, This->glDescription.textureName)");
4144         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4145         checkGLcall("glTexParameteri");
4146         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4147         checkGLcall("glTexParameteri");
4148
4149         coords[0].x = rect.left;
4150         coords[0].z = 0;
4151
4152         coords[1].x = rect.left;
4153         coords[1].z = 0;
4154
4155         coords[2].x = rect.right;
4156         coords[2].z = 0;
4157
4158         coords[3].x = rect.right;
4159         coords[3].z = 0;
4160
4161         coords[0].y = rect.top;
4162         coords[1].y = rect.bottom;
4163         coords[2].y = rect.bottom;
4164         coords[3].y = rect.top;
4165     } else if(This->glDescription.target == GL_TEXTURE_2D) {
4166         glEnable(GL_TEXTURE_2D);
4167         checkGLcall("glEnable(GL_TEXTURE_2D)");
4168         glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
4169         checkGLcall("GL_TEXTURE_2D, This->glDescription.textureName)");
4170         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4171         checkGLcall("glTexParameteri");
4172         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4173         checkGLcall("glTexParameteri");
4174
4175         coords[0].x = (float)rect.left   / This->pow2Width;
4176         coords[0].z = 0;
4177
4178         coords[1].x = (float)rect.left   / This->pow2Width;
4179         coords[1].z = 0;
4180
4181         coords[2].x = (float)rect.right  / This->pow2Width;
4182         coords[2].z = 0;
4183
4184         coords[3].x = (float)rect.right  / This->pow2Width;
4185         coords[3].z = 0;
4186
4187         coords[0].y = (float)rect.top    / This->pow2Height;
4188         coords[1].y = (float)rect.bottom / This->pow2Height;
4189         coords[2].y = (float)rect.bottom / This->pow2Height;
4190         coords[3].y = (float)rect.top    / This->pow2Height;
4191     } else {
4192         /* Must be a cube map */
4193         glEnable(GL_TEXTURE_CUBE_MAP_ARB);
4194         checkGLcall("glEnable(GL_TEXTURE_CUBE_MAP_ARB)");
4195         glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, This->glDescription.textureName);
4196         checkGLcall("GL_TEXTURE_CUBE_MAP_ARB, This->glDescription.textureName)");
4197         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4198         checkGLcall("glTexParameteri");
4199         glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4200         checkGLcall("glTexParameteri");
4201
4202         switch(This->glDescription.target) {
4203             case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4204                 coords[0].x =  1;   coords[0].y = -1;   coords[0].z =  1;
4205                 coords[1].x =  1;   coords[1].y =  1;   coords[1].z =  1;
4206                 coords[2].x =  1;   coords[2].y =  1;   coords[2].z = -1;
4207                 coords[3].x =  1;   coords[3].y = -1;   coords[3].z = -1;
4208                 break;
4209
4210             case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4211                 coords[0].x = -1;   coords[0].y = -1;   coords[0].z =  1;
4212                 coords[1].x = -1;   coords[1].y =  1;   coords[1].z =  1;
4213                 coords[2].x = -1;   coords[2].y =  1;   coords[2].z = -1;
4214                 coords[3].x = -1;   coords[3].y = -1;   coords[3].z = -1;
4215                 break;
4216
4217             case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4218                 coords[0].x = -1;   coords[0].y =  1;   coords[0].z =  1;
4219                 coords[1].x =  1;   coords[1].y =  1;   coords[1].z =  1;
4220                 coords[2].x =  1;   coords[2].y =  1;   coords[2].z = -1;
4221                 coords[3].x = -1;   coords[3].y =  1;   coords[3].z = -1;
4222                 break;
4223
4224             case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4225                 coords[0].x = -1;   coords[0].y = -1;   coords[0].z =  1;
4226                 coords[1].x =  1;   coords[1].y = -1;   coords[1].z =  1;
4227                 coords[2].x =  1;   coords[2].y = -1;   coords[2].z = -1;
4228                 coords[3].x = -1;   coords[3].y = -1;   coords[3].z = -1;
4229                 break;
4230
4231             case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4232                 coords[0].x = -1;   coords[0].y = -1;   coords[0].z =  1;
4233                 coords[1].x =  1;   coords[1].y = -1;   coords[1].z =  1;
4234                 coords[2].x =  1;   coords[2].y = -1;   coords[2].z =  1;
4235                 coords[3].x = -1;   coords[3].y = -1;   coords[3].z =  1;
4236                 break;
4237
4238             case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4239                 coords[0].x = -1;   coords[0].y = -1;   coords[0].z = -1;
4240                 coords[1].x =  1;   coords[1].y = -1;   coords[1].z = -1;
4241                 coords[2].x =  1;   coords[2].y = -1;   coords[2].z = -1;
4242                 coords[3].x = -1;   coords[3].y = -1;   coords[3].z = -1;
4243                 break;
4244
4245             default:
4246                 ERR("Unexpected texture target\n");
4247                 LEAVE_GL();
4248                 return;
4249         }
4250     }
4251
4252     glBegin(GL_QUADS);
4253     glTexCoord3fv(&coords[0].x);
4254     glVertex2i(rect.left, device->render_offscreen ? rect.bottom : rect.top);
4255
4256     glTexCoord3fv(&coords[1].x);
4257     glVertex2i(rect.left, device->render_offscreen ? rect.top : rect.bottom);
4258
4259     glTexCoord3fv(&coords[2].x);
4260     glVertex2i(rect.right, device->render_offscreen ? rect.top : rect.bottom);
4261
4262     glTexCoord3fv(&coords[3].x);
4263     glVertex2i(rect.right, device->render_offscreen ? rect.bottom : rect.top);
4264     glEnd();
4265     checkGLcall("glEnd");
4266
4267     if(This->glDescription.target != GL_TEXTURE_2D) {
4268         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
4269         checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
4270     } else {
4271         glDisable(GL_TEXTURE_2D);
4272         checkGLcall("glDisable(GL_TEXTURE_2D)");
4273     }
4274     LEAVE_GL();
4275
4276     hr = IWineD3DSurface_GetContainer((IWineD3DSurface*)This, &IID_IWineD3DSwapChain, (void **) &swapchain);
4277     if(hr == WINED3D_OK && swapchain) {
4278         /* Make sure to flush the buffers. This is needed in apps like Red Alert II and Tiberian SUN that use multiple WGL contexts. */
4279         if(((IWineD3DSwapChainImpl*)swapchain)->frontBuffer == (IWineD3DSurface*)This ||
4280            ((IWineD3DSwapChainImpl*)swapchain)->num_contexts >= 2)
4281             glFlush();
4282
4283         IWineD3DSwapChain_Release(swapchain);
4284     } else {
4285         /* We changed the filtering settings on the texture. Inform the container about this to get the filters
4286          * reset properly next draw
4287          */
4288         hr = IWineD3DSurface_GetContainer((IWineD3DSurface*)This, &IID_IWineD3DBaseTexture, (void **) &texture);
4289         if(hr == WINED3D_OK && texture) {
4290             ((IWineD3DBaseTextureImpl *) texture)->baseTexture.states[WINED3DTEXSTA_MAGFILTER] = WINED3DTEXF_POINT;
4291             ((IWineD3DBaseTextureImpl *) texture)->baseTexture.states[WINED3DTEXSTA_MINFILTER] = WINED3DTEXF_POINT;
4292             ((IWineD3DBaseTextureImpl *) texture)->baseTexture.states[WINED3DTEXSTA_MIPFILTER] = WINED3DTEXF_NONE;
4293             IWineD3DBaseTexture_Release(texture);
4294         }
4295     }
4296 }
4297
4298 /*****************************************************************************
4299  * IWineD3DSurface::LoadLocation
4300  *
4301  * Copies the current surface data from wherever it is to the requested
4302  * location. The location is one of the surface flags, SFLAG_INSYSMEM,
4303  * SFLAG_INTEXTURE and SFLAG_INDRAWABLE. When the surface is current in
4304  * multiple locations, the gl texture is preferred over the drawable, which is
4305  * preferred over system memory. The PBO counts as system memory. If rect is
4306  * not NULL, only the specified rectangle is copied (only supported for
4307  * sysmem<->drawable copies at the moment). If rect is NULL, the destination
4308  * location is marked up to date after the copy.
4309  *
4310  * Parameters:
4311  *  flag: Surface location flag to be updated
4312  *  rect: rectangle to be copied
4313  *
4314  * Returns:
4315  *  WINED3D_OK on success
4316  *  WINED3DERR_DEVICELOST on an internal error
4317  *
4318  *****************************************************************************/
4319 static HRESULT WINAPI IWineD3DSurfaceImpl_LoadLocation(IWineD3DSurface *iface, DWORD flag, const RECT *rect) {
4320     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
4321     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
4322     IWineD3DSwapChain *swapchain = NULL;
4323     GLenum format, internal, type;
4324     CONVERT_TYPES convert;
4325     int bpp;
4326     int width, pitch, outpitch;
4327     BYTE *mem;
4328
4329     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
4330         if (SUCCEEDED(IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **)&swapchain))) {
4331             TRACE("Surface %p is an onscreen surface\n", iface);
4332
4333             IWineD3DSwapChain_Release(swapchain);
4334         } else {
4335             /* With ORM_FBO, SFLAG_INTEXTURE and SFLAG_INDRAWABLE are the same for offscreen targets.
4336              * Prefer SFLAG_INTEXTURE. */
4337             if (flag == SFLAG_INDRAWABLE) flag = SFLAG_INTEXTURE;
4338         }
4339     }
4340
4341     TRACE("(%p)->(%s, %p)\n", iface,
4342           flag == SFLAG_INSYSMEM ? "SFLAG_INSYSMEM" : flag == SFLAG_INDRAWABLE ? "SFLAG_INDRAWABLE" : "SFLAG_INTEXTURE",
4343           rect);
4344     if(rect) {
4345         TRACE("Rectangle: (%d,%d)-(%d,%d)\n", rect->left, rect->top, rect->right, rect->bottom);
4346     }
4347
4348     if(This->Flags & flag) {
4349         TRACE("Location already up to date\n");
4350         return WINED3D_OK;
4351     }
4352
4353     if(!(This->Flags & SFLAG_LOCATIONS)) {
4354         ERR("Surface does not have any up to date location\n");
4355         This->Flags |= SFLAG_LOST;
4356         return WINED3DERR_DEVICELOST;
4357     }
4358
4359     if(flag == SFLAG_INSYSMEM) {
4360         surface_prepare_system_memory(This);
4361
4362         /* Download the surface to system memory */
4363         if(This->Flags & SFLAG_INTEXTURE) {
4364             if(!device->isInDraw) ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
4365             surface_bind_and_dirtify(This);
4366
4367             surface_download_data(This);
4368         } else {
4369             read_from_framebuffer(This, rect,
4370                                   This->resource.allocatedMemory,
4371                                   IWineD3DSurface_GetPitch(iface));
4372         }
4373     } else if(flag == SFLAG_INDRAWABLE) {
4374         if(This->Flags & SFLAG_INTEXTURE) {
4375             surface_blt_to_drawable(This, rect);
4376         } else {
4377             d3dfmt_get_conv(This, TRUE /* We need color keying */, FALSE /* We won't use textures */, &format, &internal, &type, &convert, &bpp, This->srgb);
4378
4379             /* The width is in 'length' not in bytes */
4380             width = This->currentDesc.Width;
4381             pitch = IWineD3DSurface_GetPitch(iface);
4382
4383             /* Don't use PBOs for converted surfaces. During PBO conversion we look at SFLAG_CONVERTED
4384              * but it isn't set (yet) in all cases it is getting called. */
4385             if((convert != NO_CONVERSION) && (This->Flags & SFLAG_PBO)) {
4386                 TRACE("Removing the pbo attached to surface %p\n", This);
4387                 surface_remove_pbo(This);
4388             }
4389
4390             if((convert != NO_CONVERSION) && This->resource.allocatedMemory) {
4391                 int height = This->currentDesc.Height;
4392
4393                 /* Stick to the alignment for the converted surface too, makes it easier to load the surface */
4394                 outpitch = width * bpp;
4395                 outpitch = (outpitch + device->surface_alignment - 1) & ~(device->surface_alignment - 1);
4396
4397                 mem = HeapAlloc(GetProcessHeap(), 0, outpitch * height);
4398                 if(!mem) {
4399                     ERR("Out of memory %d, %d!\n", outpitch, height);
4400                     return WINED3DERR_OUTOFVIDEOMEMORY;
4401                 }
4402                 d3dfmt_convert_surface(This->resource.allocatedMemory, mem, pitch, width, height, outpitch, convert, This);
4403
4404                 This->Flags |= SFLAG_CONVERTED;
4405             } else {
4406                 This->Flags &= ~SFLAG_CONVERTED;
4407                 mem = This->resource.allocatedMemory;
4408             }
4409
4410             flush_to_framebuffer_drawpixels(This, format, type, bpp, mem);
4411
4412             /* Don't delete PBO memory */
4413             if((mem != This->resource.allocatedMemory) && !(This->Flags & SFLAG_PBO))
4414                 HeapFree(GetProcessHeap(), 0, mem);
4415         }
4416     } else /* if(flag == SFLAG_INTEXTURE) */ {
4417         if (This->Flags & SFLAG_INDRAWABLE) {
4418             read_from_framebuffer_texture(This);
4419         } else { /* Upload from system memory */
4420             d3dfmt_get_conv(This, TRUE /* We need color keying */, TRUE /* We will use textures */, &format, &internal, &type, &convert, &bpp, This->srgb);
4421
4422             if(!device->isInDraw) ActivateContext(device, device->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
4423             surface_bind_and_dirtify(This);
4424             ENTER_GL();
4425
4426             /* The only place where LoadTexture() might get called when isInDraw=1
4427              * is ActivateContext where lastActiveRenderTarget is preloaded.
4428              */
4429             if(iface == device->lastActiveRenderTarget && device->isInDraw)
4430                 ERR("Reading back render target but SFLAG_INDRAWABLE not set\n");
4431
4432             /* Otherwise: System memory copy must be most up to date */
4433
4434             if(This->CKeyFlags & WINEDDSD_CKSRCBLT) {
4435                 This->Flags |= SFLAG_GLCKEY;
4436                 This->glCKey = This->SrcBltCKey;
4437             }
4438             else This->Flags &= ~SFLAG_GLCKEY;
4439
4440             /* The width is in 'length' not in bytes */
4441             width = This->currentDesc.Width;
4442             pitch = IWineD3DSurface_GetPitch(iface);
4443
4444             /* Don't use PBOs for converted surfaces. During PBO conversion we look at SFLAG_CONVERTED
4445              * but it isn't set (yet) in all cases it is getting called. */
4446             if((convert != NO_CONVERSION) && (This->Flags & SFLAG_PBO)) {
4447                 TRACE("Removing the pbo attached to surface %p\n", This);
4448                 surface_remove_pbo(This);
4449             }
4450
4451             if((convert != NO_CONVERSION) && This->resource.allocatedMemory) {
4452                 int height = This->currentDesc.Height;
4453
4454                 /* Stick to the alignment for the converted surface too, makes it easier to load the surface */
4455                 outpitch = width * bpp;
4456                 outpitch = (outpitch + device->surface_alignment - 1) & ~(device->surface_alignment - 1);
4457
4458                 mem = HeapAlloc(GetProcessHeap(), 0, outpitch * height);
4459                 if(!mem) {
4460                     ERR("Out of memory %d, %d!\n", outpitch, height);
4461                     return WINED3DERR_OUTOFVIDEOMEMORY;
4462                 }
4463                 d3dfmt_convert_surface(This->resource.allocatedMemory, mem, pitch, width, height, outpitch, convert, This);
4464
4465                 This->Flags |= SFLAG_CONVERTED;
4466             } else if( (This->resource.format == WINED3DFMT_P8) && (GL_SUPPORT(EXT_PALETTED_TEXTURE) || GL_SUPPORT(ARB_FRAGMENT_PROGRAM)) ) {
4467                 d3dfmt_p8_upload_palette(iface, convert);
4468                 This->Flags &= ~SFLAG_CONVERTED;
4469                 mem = This->resource.allocatedMemory;
4470             } else {
4471                 This->Flags &= ~SFLAG_CONVERTED;
4472                 mem = This->resource.allocatedMemory;
4473             }
4474
4475             /* Make sure the correct pitch is used */
4476             glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
4477
4478             if ((This->Flags & SFLAG_NONPOW2) && !(This->Flags & SFLAG_OVERSIZE)) {
4479                 TRACE("non power of two support\n");
4480                 if(!(This->Flags & SFLAG_ALLOCATED)) {
4481                     surface_allocate_surface(This, internal, This->pow2Width, This->pow2Height, format, type);
4482                 }
4483                 if (mem || (This->Flags & SFLAG_PBO)) {
4484                     surface_upload_data(This, internal, This->currentDesc.Width, This->currentDesc.Height, format, type, mem);
4485                 }
4486             } else {
4487                 /* When making the realloc conditional, keep in mind that GL_APPLE_client_storage may be in use, and This->resource.allocatedMemory
4488                  * changed. So also keep track of memory changes. In this case the texture has to be reallocated
4489                  */
4490                 if(!(This->Flags & SFLAG_ALLOCATED)) {
4491                     surface_allocate_surface(This, internal, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type);
4492                 }
4493                 if (mem || (This->Flags & SFLAG_PBO)) {
4494                     surface_upload_data(This, internal, This->glRect.right - This->glRect.left, This->glRect.bottom - This->glRect.top, format, type, mem);
4495                 }
4496             }
4497
4498             /* Restore the default pitch */
4499             glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
4500             LEAVE_GL();
4501
4502             /* Don't delete PBO memory */
4503             if((mem != This->resource.allocatedMemory) && !(This->Flags & SFLAG_PBO))
4504                 HeapFree(GetProcessHeap(), 0, mem);
4505         }
4506     }
4507
4508     if(rect == NULL) {
4509         This->Flags |= flag;
4510     }
4511
4512     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && !swapchain
4513             && (This->Flags & (SFLAG_INTEXTURE | SFLAG_INDRAWABLE))) {
4514         /* With ORM_FBO, SFLAG_INTEXTURE and SFLAG_INDRAWABLE are the same for offscreen targets. */
4515         This->Flags |= (SFLAG_INTEXTURE | SFLAG_INDRAWABLE);
4516     }
4517
4518     return WINED3D_OK;
4519 }
4520
4521 HRESULT WINAPI IWineD3DSurfaceImpl_SetContainer(IWineD3DSurface *iface, IWineD3DBase *container) {
4522     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
4523     IWineD3DSwapChain *swapchain = NULL;
4524
4525     /* Update the drawable size method */
4526     if(container) {
4527         IWineD3DBase_QueryInterface(container, &IID_IWineD3DSwapChain, (void **) &swapchain);
4528     }
4529     if(swapchain) {
4530         This->get_drawable_size = get_drawable_size_swapchain;
4531         IWineD3DSwapChain_Release(swapchain);
4532     } else if(This->resource.usage & WINED3DUSAGE_RENDERTARGET) {
4533         switch(wined3d_settings.offscreen_rendering_mode) {
4534             case ORM_FBO:        This->get_drawable_size = get_drawable_size_fbo;        break;
4535             case ORM_PBUFFER:    This->get_drawable_size = get_drawable_size_pbuffer;    break;
4536             case ORM_BACKBUFFER: This->get_drawable_size = get_drawable_size_backbuffer; break;
4537         }
4538     }
4539
4540     return IWineD3DBaseSurfaceImpl_SetContainer(iface, container);
4541 }
4542
4543 static WINED3DSURFTYPE WINAPI IWineD3DSurfaceImpl_GetImplType(IWineD3DSurface *iface) {
4544     return SURFACE_OPENGL;
4545 }
4546
4547 static HRESULT WINAPI IWineD3DSurfaceImpl_DrawOverlay(IWineD3DSurface *iface) {
4548     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
4549     HRESULT hr;
4550
4551     /* If there's no destination surface there is nothing to do */
4552     if(!This->overlay_dest) return WINED3D_OK;
4553
4554     /* Blt calls ModifyLocation on the dest surface, which in turn calls DrawOverlay to
4555      * update the overlay. Prevent an endless recursion
4556      */
4557     if(This->overlay_dest->Flags & SFLAG_INOVERLAYDRAW) {
4558         return WINED3D_OK;
4559     }
4560     This->overlay_dest->Flags |= SFLAG_INOVERLAYDRAW;
4561     hr = IWineD3DSurfaceImpl_Blt((IWineD3DSurface *) This->overlay_dest, &This->overlay_destrect,
4562                                  iface, &This->overlay_srcrect, WINEDDBLT_WAIT,
4563                                  NULL, WINED3DTEXF_LINEAR);
4564     This->overlay_dest->Flags &= ~SFLAG_INOVERLAYDRAW;
4565
4566     return hr;
4567 }
4568
4569 const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl =
4570 {
4571     /* IUnknown */
4572     IWineD3DBaseSurfaceImpl_QueryInterface,
4573     IWineD3DBaseSurfaceImpl_AddRef,
4574     IWineD3DSurfaceImpl_Release,
4575     /* IWineD3DResource */
4576     IWineD3DBaseSurfaceImpl_GetParent,
4577     IWineD3DBaseSurfaceImpl_GetDevice,
4578     IWineD3DBaseSurfaceImpl_SetPrivateData,
4579     IWineD3DBaseSurfaceImpl_GetPrivateData,
4580     IWineD3DBaseSurfaceImpl_FreePrivateData,
4581     IWineD3DBaseSurfaceImpl_SetPriority,
4582     IWineD3DBaseSurfaceImpl_GetPriority,
4583     IWineD3DSurfaceImpl_PreLoad,
4584     IWineD3DSurfaceImpl_UnLoad,
4585     IWineD3DBaseSurfaceImpl_GetType,
4586     /* IWineD3DSurface */
4587     IWineD3DBaseSurfaceImpl_GetContainer,
4588     IWineD3DBaseSurfaceImpl_GetDesc,
4589     IWineD3DSurfaceImpl_LockRect,
4590     IWineD3DSurfaceImpl_UnlockRect,
4591     IWineD3DSurfaceImpl_GetDC,
4592     IWineD3DSurfaceImpl_ReleaseDC,
4593     IWineD3DSurfaceImpl_Flip,
4594     IWineD3DSurfaceImpl_Blt,
4595     IWineD3DBaseSurfaceImpl_GetBltStatus,
4596     IWineD3DBaseSurfaceImpl_GetFlipStatus,
4597     IWineD3DBaseSurfaceImpl_IsLost,
4598     IWineD3DBaseSurfaceImpl_Restore,
4599     IWineD3DSurfaceImpl_BltFast,
4600     IWineD3DBaseSurfaceImpl_GetPalette,
4601     IWineD3DBaseSurfaceImpl_SetPalette,
4602     IWineD3DSurfaceImpl_RealizePalette,
4603     IWineD3DBaseSurfaceImpl_SetColorKey,
4604     IWineD3DBaseSurfaceImpl_GetPitch,
4605     IWineD3DSurfaceImpl_SetMem,
4606     IWineD3DBaseSurfaceImpl_SetOverlayPosition,
4607     IWineD3DBaseSurfaceImpl_GetOverlayPosition,
4608     IWineD3DBaseSurfaceImpl_UpdateOverlayZOrder,
4609     IWineD3DBaseSurfaceImpl_UpdateOverlay,
4610     IWineD3DBaseSurfaceImpl_SetClipper,
4611     IWineD3DBaseSurfaceImpl_GetClipper,
4612     /* Internal use: */
4613     IWineD3DSurfaceImpl_AddDirtyRect,
4614     IWineD3DSurfaceImpl_LoadTexture,
4615     IWineD3DSurfaceImpl_BindTexture,
4616     IWineD3DSurfaceImpl_SaveSnapshot,
4617     IWineD3DSurfaceImpl_SetContainer,
4618     IWineD3DSurfaceImpl_SetGlTextureDesc,
4619     IWineD3DSurfaceImpl_GetGlDesc,
4620     IWineD3DSurfaceImpl_GetData,
4621     IWineD3DSurfaceImpl_SetFormat,
4622     IWineD3DSurfaceImpl_PrivateSetup,
4623     IWineD3DSurfaceImpl_ModifyLocation,
4624     IWineD3DSurfaceImpl_LoadLocation,
4625     IWineD3DSurfaceImpl_GetImplType,
4626     IWineD3DSurfaceImpl_DrawOverlay
4627 };
4628 #undef GLINFO_LOCATION
4629
4630 #define GLINFO_LOCATION device->adapter->gl_info
4631 static HRESULT ffp_blit_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
4632 static void ffp_blit_free(IWineD3DDevice *iface) { }
4633
4634 static HRESULT ffp_blit_set(IWineD3DDevice *iface, WINED3DFORMAT fmt, GLenum textype, UINT width, UINT height) {
4635     glEnable(textype);
4636     checkGLcall("glEnable(textype)");
4637     return WINED3D_OK;
4638 }
4639
4640 static void ffp_blit_unset(IWineD3DDevice *iface) {
4641     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface;
4642     glDisable(GL_TEXTURE_2D);
4643     checkGLcall("glDisable(GL_TEXTURE_2D)");
4644     if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
4645         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
4646         checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
4647     }
4648     if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
4649         glDisable(GL_TEXTURE_RECTANGLE_ARB);
4650         checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
4651     }
4652 }
4653
4654 static BOOL ffp_blit_conv_supported(WINED3DFORMAT fmt) {
4655     TRACE("Checking blit format support for format %s: [FAILED]\n", debug_d3dformat(fmt));
4656     return FALSE;
4657 }
4658
4659 const struct blit_shader ffp_blit =  {
4660     ffp_blit_alloc,
4661     ffp_blit_free,
4662     ffp_blit_set,
4663     ffp_blit_unset,
4664     ffp_blit_conv_supported
4665 };