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