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