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