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