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