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