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