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