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