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