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