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