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