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