diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index bc44ca3cedef5e7ed1086f5e74abeabc9eddfe73..92106aa065d6848dc92f66342882d609be01ccd2 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -362,9 +362,11 @@ HRESULT WINAPI IWineD3DSurfaceImpl_LockRect(IWineD3DSurface *iface, WINED3DLOCKE
         TRACE("locking an ordinarary surface\n");
         /* Check to see if memory has already been allocated from the surface*/
         if ((NULL == This->resource.allocatedMemory) ||
-            (This->Flags & SFLAG_NEWDC) ){ /* TODO: check to see if an update has been performed on the surface (an update could just clobber allocatedMemory */
+            (This->Flags & SFLAG_GLDIRTY) ){ /* TODO: check to see if an update has been performed on the surface (an update could just clobber allocatedMemory */
             /* Non-system memory surfaces */
 
+            This->Flags &= ~SFLAG_GLDIRTY;
+
             /*Surface has no memory currently allocated to it!*/
             TRACE("(%p) Locking rect\n" , This);
             if(!This->resource.allocatedMemory) {
@@ -1066,6 +1068,9 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
             memcpy(This->dib.bitmap_data, This->resource.allocatedMemory, This->resource.size);
             /* We won't need that any more */
             HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
+        } else {
+            /* This is to make LockRect read the gl Texture although memory is allocated */
+            This->Flags |= SFLAG_GLDIRTY;
         }
 
         /* Use the dib section from now on */
@@ -1079,9 +1084,6 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
                       This->palette ? This->palette->hpal : 0,
                       FALSE);
 
-        /* This is to make LockRect read the gl Texture although memory is allocated */
-        This->Flags |= SFLAG_NEWDC;
-
         This->Flags |= SFLAG_DIBSECTION;
     }
 
@@ -1090,7 +1092,6 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
                                   &lock,
                                   NULL,
                                   0);
-    This->Flags &= ~SFLAG_NEWDC;
     if(FAILED(hr)) {
         ERR("IWineD3DSurface_LockRect failed with hr = %08lx\n", hr);
         /* keep the dib section */
@@ -1944,11 +1945,532 @@ HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DSurface
     return IWineD3DDevice_Present(D3D, NULL, NULL, 0, NULL);
 }
 
-HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
-    FIXME("This is unimplemented for now(d3d7 merge)\n");
+/* Not called from the VTable */
+HRESULT WINAPI IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
+    D3DRECT rect;
+    IWineD3DDeviceImpl *myDevice = This->resource.wineD3DDevice;
+    IWineD3DSwapChainImpl *swapchain = NULL;
+    IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
+    BOOL SrcOK = TRUE;
+
+    TRACE("(%p)->(%p,%p,%p,%08lx,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
+
+    /* Get the swapchain. One of the surfaces has to be a primary surface */
+    IWineD3DSurface_GetContainer( (IWineD3DSurface *) This, &IID_IWineD3DSwapChain, (void **)&swapchain);
+    if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
+    else if(Src) {
+        IWineD3DSurface_GetContainer( (IWineD3DSurface *) Src, &IID_IWineD3DSwapChain, (void **)&swapchain);
+        if(swapchain) IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
+        else return WINED3DERR_INVALIDCALL;
+    } else {
+        swapchain = NULL;
+    }
+
+    if (DestRect) {
+        rect.x1 = DestRect->left;
+        rect.y1 = DestRect->top;
+        rect.x2 = DestRect->right;
+        rect.y2 = DestRect->bottom;
+    } else {
+        rect.x1 = 0;
+        rect.y1 = 0;
+        rect.x2 = This->currentDesc.Width;
+        rect.y2 = This->currentDesc.Height;
+    }
+
+    /* Half-life does a Blt from the back buffer to the front buffer,
+     * Full surface size, no flags... Use present instead
+     */
+    if(Src)
+    {
+        /* First, check if we can do a Flip */
+
+        /* Check rects - IWineD3DDevice_Present doesn't handle them */
+        if( SrcRect ) {
+            if( (SrcRect->left == 0) && (SrcRect->top == 0) &&
+                (SrcRect->right == Src->currentDesc.Width) && (SrcRect->bottom == Src->currentDesc.Height) ) {
+                SrcOK = TRUE;
+            }
+        } else {
+            SrcOK = TRUE;
+        }
+
+        /* Check the Destination rect and the surface sizes */
+        if(SrcOK &&
+           (rect.x1 == 0) && (rect.y1 == 0) &&
+           (rect.x2 ==  This->currentDesc.Width) && (rect.y2 == This->currentDesc.Height) &&
+           (This->currentDesc.Width == Src->currentDesc.Width) &&
+           (This->currentDesc.Height == Src->currentDesc.Height)) {
+            /* These flags are unimportant for the flag check, remove them */
+
+            if((Flags & ~(DDBLT_DONOTWAIT | DDBLT_WAIT)) == 0) {
+                if( ((IWineD3DSurface *) This == swapchain->frontBuffer) && ((IWineD3DSurface *) Src == swapchain->backBuffer) ) {
+
+                    D3DSWAPEFFECT orig_swap = swapchain->presentParms.SwapEffect;
+
+                    /* The idea behind this is that a glReadPixels and a glDrawPixels call
+                     * take very long, while a flip is fast.
+                     * This applies to Half-Life, which does such Blts every time it finished
+                     * a frame, and to Prince of Persia 3D, which uses this to draw at least the main
+                     * menu. This is also used by all apps when they do windowed rendering
+                     *
+                     * The problem is that flipping is not really the same as copying. After a
+                     * Blt the front buffer is a copy of the back buffer, and the back buffer is
+                     * untouched. Therefore it's necessary to override the swap effect
+                     * and to set it back after the flip.
+                     */
+
+                    swapchain->presentParms.SwapEffect = WINED3DSWAPEFFECT_COPY;
+
+                    TRACE("Full screen back buffer -> front buffer blt, performing a flip instead\n");
+                    IWineD3DDevice_Present((IWineD3DDevice *) This->resource.wineD3DDevice,
+                                            NULL, NULL, 0, NULL);
+
+                    swapchain->presentParms.SwapEffect = orig_swap;
+
+                    return WINED3D_OK;
+                }
+            }
+        }
+
+        /* Blt from texture to rendertarget? */
+        if( ( ( (IWineD3DSurface *) This == swapchain->frontBuffer) ||
+              ((IWineD3DSurface *) This == swapchain->backBuffer) )
+              &&
+              ( ( (IWineD3DSurface *) Src != swapchain->frontBuffer) &&
+                ( (IWineD3DSurface *) Src != swapchain->backBuffer) ) ) {
+            float glTexCoord[4];
+            DWORD oldCKey;
+            GLint oldLight, oldFog, oldDepth, oldBlend, oldCull, oldAlpha;
+            GLint alphafunc;
+            GLclampf alpharef;
+            GLint oldStencil;
+            RECT SourceRectangle;
+            GLint oldDraw;
+
+            TRACE("Blt from surface %p to rendertarget %p\n", Src, This);
+
+            if(SrcRect) {
+                SourceRectangle.left = SrcRect->left;
+                SourceRectangle.right = SrcRect->right;
+                SourceRectangle.top = SrcRect->top;
+                SourceRectangle.bottom = SrcRect->bottom;
+            } else {
+                SourceRectangle.left = 0;
+                SourceRectangle.right = Src->currentDesc.Width;
+                SourceRectangle.top = 0;
+                SourceRectangle.bottom = Src->currentDesc.Height;
+            }
+
+            if(!CalculateTexRect(Src, &SourceRectangle, glTexCoord)) {
+                /* Fall back to software */
+                WARN("(%p) Source texture area (%ld,%ld)-(%ld,%ld) is too big\n", Src,
+                     SourceRectangle.left, SourceRectangle.top,
+                     SourceRectangle.right, SourceRectangle.bottom);
+                return WINED3DERR_INVALIDCALL;
+            }
+
+            /* Color keying: Check if we have to do a color keyed blt,
+             * and if not check if a color key is activated.
+             */
+            oldCKey = Src->CKeyFlags;
+            if(!(Flags & DDBLT_KEYSRC) && 
+               Src->CKeyFlags & DDSD_CKSRCBLT) {
+                /* Ok, the surface has a color key, but we shall not use it - 
+                 * Deactivate it for now and dirtify the surface to reload it
+                 */
+                Src->CKeyFlags &= ~DDSD_CKSRCBLT;
+                Src->Flags |= SFLAG_DIRTY;
+            }
+
+            /* Now load the surface */
+            IWineD3DSurface_PreLoad((IWineD3DSurface *) Src);
+
+            ENTER_GL();
+
+            /* Save all the old stuff until we have a proper opengl state manager */
+            oldLight = glIsEnabled(GL_LIGHTING);
+            oldFog = glIsEnabled(GL_FOG);
+            oldDepth = glIsEnabled(GL_DEPTH_TEST);
+            oldBlend = glIsEnabled(GL_BLEND);
+            oldCull = glIsEnabled(GL_CULL_FACE);
+            oldAlpha = glIsEnabled(GL_ALPHA_TEST);
+            oldStencil = glIsEnabled(GL_STENCIL_TEST);
+
+            glGetIntegerv(GL_ALPHA_TEST_FUNC, &alphafunc);
+            checkGLcall("glGetFloatv GL_ALPHA_TEST_FUNC");
+            glGetFloatv(GL_ALPHA_TEST_REF, &alpharef);
+            checkGLcall("glGetFloatv GL_ALPHA_TEST_REF");
+
+            glGetIntegerv(GL_DRAW_BUFFER, &oldDraw);
+            if(This == (IWineD3DSurfaceImpl *) swapchain->frontBuffer) {
+                TRACE("Drawing to front buffer\n");
+                glDrawBuffer(GL_FRONT);
+                checkGLcall("glDrawBuffer GL_FRONT");
+            }
+
+            /* Unbind the old texture */
+            glBindTexture(GL_TEXTURE_2D, 0);
+
+            /* We use texture unit 0 for blts */
+            GLACTIVETEXTURE(0);
+
+            /* Disable some fancy graphics effects */
+            glDisable(GL_LIGHTING);
+            checkGLcall("glDisable GL_LIGHTING");
+            glDisable(GL_DEPTH_TEST);
+            checkGLcall("glDisable GL_DEPTH_TEST");
+            glDisable(GL_FOG);
+            checkGLcall("glDisable GL_FOG");
+            glDisable(GL_BLEND);
+            checkGLcall("glDisable GL_BLEND");
+            glDisable(GL_CULL_FACE);
+            checkGLcall("glDisable GL_CULL_FACE");
+            glDisable(GL_STENCIL_TEST);
+            checkGLcall("glDisable GL_STENCIL_TEST");
+
+            /* Ok, we need 2d textures, but not 1D or 3D */
+            glDisable(GL_TEXTURE_1D);
+            checkGLcall("glDisable GL_TEXTURE_1D");
+            glEnable(GL_TEXTURE_2D);
+            checkGLcall("glEnable GL_TEXTURE_2D");
+            glDisable(GL_TEXTURE_3D);
+            checkGLcall("glDisable GL_TEXTURE_3D");
+
+            /* Bind the texture */
+            glBindTexture(GL_TEXTURE_2D, Src->glDescription.textureName);
+            checkGLcall("glBindTexture");
+
+            glEnable(GL_SCISSOR_TEST);
+
+            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+
+            /* No filtering for blts */
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
+                            GL_NEAREST);
+            checkGLcall("glTexParameteri");
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
+                            GL_NEAREST);
+            checkGLcall("glTexParameteri");
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+            checkGLcall("glTexEnvi");
+
+            /* This is for color keying */
+            if(Flags & DDBLT_KEYSRC) {
+                glEnable(GL_ALPHA_TEST);
+                checkGLcall("glEnable GL_ALPHA_TEST");
+                glAlphaFunc(GL_NOTEQUAL, 0.0);
+                checkGLcall("glAlphaFunc\n");
+            } else {
+                glDisable(GL_ALPHA_TEST);
+                checkGLcall("glDisable GL_ALPHA_TEST");
+            }
+
+            /* Draw a textured quad
+             */
+            if ( TRUE ) {
+                double X, Y, height, width, minZ, maxZ;
+                myDevice->last_was_rhw = FALSE;
+                myDevice->viewport_changed = FALSE;
+
+                /* Transformed already into viewport coordinates, so we do not need transform
+                   matrices. Reset all matrices to identity and leave the default matrix in world
+                   mode.                                                                         */
+                glMatrixMode(GL_MODELVIEW);
+                checkGLcall("glMatrixMode");
+                glLoadIdentity();
+                checkGLcall("glLoadIdentity");
+
+                glMatrixMode(GL_PROJECTION);
+                checkGLcall("glMatrixMode");
+                glLoadIdentity();
+                checkGLcall("glLoadIdentity");
+
+                /* Set up the viewport to be full viewport */
+                X      = myDevice->stateBlock->viewport.X;
+                Y      = myDevice->stateBlock->viewport.Y;
+                height = myDevice->stateBlock->viewport.Height;
+                width  = myDevice->stateBlock->viewport.Width;
+                minZ   = myDevice->stateBlock->viewport.MinZ;
+                maxZ   = myDevice->stateBlock->viewport.MaxZ;
+                TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
+                glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
+                checkGLcall("glOrtho");
+
+                /* Window Coord 0 is the middle of the first pixel, so translate by half
+                   a pixel (See comment above glTranslate below)                         */
+                glTranslatef(0.375, 0.375, 0);
+                checkGLcall("glTranslatef(0.375, 0.375, 0)");
+            }
+
+            glBegin(GL_QUADS);
+
+            glColor3d(1.0f, 1.0f, 1.0f);
+            glTexCoord2f(glTexCoord[0], glTexCoord[2]);
+            glVertex3f(rect.x1,
+                       rect.y1,
+                       0.0);
+
+            glTexCoord2f(glTexCoord[0], glTexCoord[3]);
+            glVertex3f(rect.x1, rect.y2, 0.0);
+
+            glTexCoord2f(glTexCoord[1], glTexCoord[3]);
+            glVertex3f(rect.x2,
+                       rect.y2,
+                       0.0);
+
+            glTexCoord2f(glTexCoord[1], glTexCoord[2]);
+            glVertex3f(rect.x2,
+                       rect.y1,
+                       0.0);
+            glEnd();
+            checkGLcall("glEnd");
+
+            /* Unbind the texture */
+            glBindTexture(GL_TEXTURE_2D, 0);
+            checkGLcall("glEnable glBindTexture");
+
+            /* Restore the old settings */
+            if(oldLight) {
+                glEnable(GL_LIGHTING);
+                checkGLcall("glEnable GL_LIGHTING");
+            }
+            if(oldFog) {
+                glEnable(GL_FOG);
+                checkGLcall("glEnable GL_FOG");
+            }
+            if(oldDepth) {
+                glEnable(GL_DEPTH_TEST);
+                checkGLcall("glEnable GL_DEPTH_TEST");
+            }
+            if(oldBlend) {
+                glEnable(GL_BLEND);
+                checkGLcall("glEnable GL_BLEND");
+            }
+            if(oldCull) {
+                glEnable(GL_CULL_FACE);
+                checkGLcall("glEnable GL_CULL_FACE");
+            }
+            if(oldStencil) {
+                glEnable(GL_STENCIL_TEST);
+                checkGLcall("glEnable GL_STENCIL_TEST");
+            }
+            if(!oldAlpha) {
+                glDisable(GL_ALPHA_TEST);
+                checkGLcall("glDisable GL_ALPHA_TEST");
+            } else {
+                glEnable(GL_ALPHA_TEST);
+                checkGLcall("glEnable GL_ALPHA_TEST");
+            }
+
+            glAlphaFunc(alphafunc, alpharef);
+            checkGLcall("glAlphaFunc\n");
+
+            if(This == (IWineD3DSurfaceImpl *) swapchain->frontBuffer && oldDraw == GL_BACK) {
+                glDrawBuffer(oldDraw);
+            }
+
+            /* Restore the color key */
+            if(oldCKey != Src->CKeyFlags) {
+                Src->CKeyFlags = oldCKey;
+                Src->Flags |= SFLAG_DIRTY;
+            }
+
+            LEAVE_GL();
+
+            return WINED3D_OK;
+        }
+
+
+        /* Blt from rendertarget to texture? */
+        if( (SrcSurface == swapchain->frontBuffer) ||
+            (SrcSurface == swapchain->backBuffer) ) {
+            if( ( (IWineD3DSurface *) This != swapchain->frontBuffer) &&
+                ( (IWineD3DSurface *) This != swapchain->backBuffer) ) {
+                UINT row;
+                D3DRECT srect;
+                float xrel, yrel;
+
+                TRACE("Blt from rendertarget to texture\n");
+
+                /* Call preload for the surface to make sure it isn't dirty */
+                IWineD3DSurface_PreLoad((IWineD3DSurface *) This);
+
+                if(SrcRect) {
+                    srect.x1 = SrcRect->left;
+                    srect.y1 = SrcRect->top;
+                    srect.x2 = SrcRect->right;
+                    srect.y2 = SrcRect->bottom;
+                } else {
+                    srect.x1 = 0;
+                    srect.y1 = 0;
+                    srect.x2 = Src->currentDesc.Width;
+                    srect.y2 = Src->currentDesc.Height;
+                }
+
+                ENTER_GL();
+
+                /* Bind the target texture */
+                glBindTexture(GL_TEXTURE_2D, This->glDescription.textureName);
+                checkGLcall("glBindTexture");
+                if(SrcSurface == swapchain->backBuffer) {
+                    glReadBuffer(GL_BACK);
+                } else {
+                    glReadBuffer(GL_FRONT);
+                }
+                checkGLcall("glReadBuffer");
+
+                xrel = (float) (srect.x2 - srect.x1) / (float) (rect.x2 - rect.x1);
+                yrel = (float) (srect.y2 - srect.y1) / (float) (rect.y2 - rect.y1);
+
+                /* I have to process this row by row to swap the image,
+                 * otherwise it would be upside down, so streching in y direction
+                 * doesn't cost extra time
+                 *
+                 * However, streching in x direction can be avoided if not necessary
+                 */
+                for(row = rect.y1; row < rect.y2; row++) {
+                    if( (xrel - 1.0 < -eps) || (xrel - 1.0 > eps)) {
+                        /* Well, that stuff works, but it's very slow.
+                         * find a better way instead
+                         */
+                        UINT col;
+                        for(col = rect.x1; col < rect.x2; col++) {
+                            glCopyTexSubImage2D(GL_TEXTURE_2D,
+                                                0, /* level */
+                                                rect.x1 + col, This->currentDesc.Height - row - 1, /* xoffset, yoffset */
+                                                srect.x1 + col * xrel, Src->currentDesc.Height - srect.y2 + row * yrel,
+                                                1, 1);
+                        }
+                    } else {
+                        glCopyTexSubImage2D(GL_TEXTURE_2D,
+                                            0, /* level */
+                                            rect.x1, This->currentDesc.Height - row - 1, /* xoffset, yoffset */
+                                            srect.x1, Src->currentDesc.Height - srect.y2 + row * yrel,
+                                            rect.x2, 1);
+                    }
+                }
+
+                vcheckGLcall("glCopyTexSubImage2D");
+                LEAVE_GL();
+
+                if(!(This->Flags & SFLAG_DONOTFREE)) {
+                    if(This->resource.allocatedMemory) HeapFree(GetProcessHeap(), 0, This->resource.allocatedMemory);
+                    This->resource.allocatedMemory = NULL;
+                } else {
+                    This->Flags |= SFLAG_GLDIRTY;
+                }
+
+                return WINED3D_OK;
+            }
+        }
+    }
+
+    if (Flags & DDBLT_COLORFILL) {
+        /* This is easy to handle for the D3D Device... */
+        DWORD color;
+        IWineD3DSwapChainImpl *implSwapChain;
+        GLint  prev_draw;
+
+        TRACE("Colorfill\n");
+
+        /* The color as given in the Blt function is in the format of the frame-buffer...
+         * 'clear' expect it in ARGB format => we need to do some conversion :-)
+         */
+        if (This->resource.format == WINED3DFMT_P8) {
+            if (This->palette) {
+                color = ((0xFF000000) |
+                          (This->palette->palents[DDBltFx->u5.dwFillColor].peRed << 16) |
+                          (This->palette->palents[DDBltFx->u5.dwFillColor].peGreen << 8) |
+                          (This->palette->palents[DDBltFx->u5.dwFillColor].peBlue));
+            } else {
+                color = 0xFF000000;
+            }
+        }
+        else if (This->resource.format == WINED3DFMT_R5G6B5) {
+            if (DDBltFx->u5.dwFillColor == 0xFFFF) {
+                color = 0xFFFFFFFF;
+            } else {
+                color = ((0xFF000000) |
+                          ((DDBltFx->u5.dwFillColor & 0xF800) << 8) |
+                          ((DDBltFx->u5.dwFillColor & 0x07E0) << 5) |
+                          ((DDBltFx->u5.dwFillColor & 0x001F) << 3));
+            }
+        }
+        else if ((This->resource.format == WINED3DFMT_R8G8B8) ||
+                  (This->resource.format == WINED3DFMT_X8R8G8B8) ) {
+            color = 0xFF000000 | DDBltFx->u5.dwFillColor;
+        }
+        else if (This->resource.format == WINED3DFMT_A8R8G8B8) {
+            color = DDBltFx->u5.dwFillColor;
+        }
+        else {
+            ERR("Wrong surface type for BLT override(Format doesn't match) !\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        /* Are we drawing to the Front buffer or the back buffer? */
+        glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
+        vcheckGLcall("glIntegerv");
+
+        TRACE("Calling GetSwapChain with mydevice = %p\n", myDevice);
+        IWineD3DDevice_GetSwapChain((IWineD3DDevice *)myDevice, 0, (IWineD3DSwapChain **)&implSwapChain);
+        IWineD3DSwapChain_Release( (IWineD3DSwapChain *) implSwapChain );
+        if(This ==  (IWineD3DSurfaceImpl*) implSwapChain->backBuffer) {
+            glDrawBuffer(GL_BACK);
+            checkGLcall("glDrawBuffer(GL_BACK)");
+        }
+        else if (This == (IWineD3DSurfaceImpl*) implSwapChain->frontBuffer) {
+            glDrawBuffer(GL_FRONT);
+            checkGLcall("glDrawBuffer(GL_FRONT)");
+        }
+        else {
+            ERR("Wrong surface type for BLT override(not on swapchain) !\n");
+            return WINED3DERR_INVALIDCALL;
+        }
+
+        TRACE("(%p) executing Render Target override, color = %lx\n", This, color);
+
+        IWineD3DDevice_Clear( (IWineD3DDevice *) myDevice,
+                              1 /* Number of rectangles */,
+                              &rect,
+                              D3DCLEAR_TARGET,
+                              color,
+                              0.0 /* Z */,
+                              0 /* Stencil */);
+
+        /* Restore the original draw buffer */
+        glDrawBuffer(prev_draw);
+        vcheckGLcall("glDrawBuffer");
+
+        return WINED3D_OK;
+    }
+
+    /* Default: Fall back to the generic blt */
     return WINED3DERR_INVALIDCALL;
 }
 
+HRESULT WINAPI IWineD3DSurfaceImpl_Blt(IWineD3DSurface *iface, RECT *DestRect, IWineD3DSurface *SrcSurface, RECT *SrcRect, DWORD Flags, DDBLTFX *DDBltFx) {
+    IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
+    IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
+    TRACE("(%p)->(%p,%p,%p,%lx,%p)\n", This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
+    TRACE("(%p): Usage is %08lx\n", This, This->resource.usage);
+
+    /* Special cases for RenderTargets */
+    if( (This->resource.usage & WINED3DUSAGE_RENDERTARGET) ||
+        ( Src && (Src->resource.usage & WINED3DUSAGE_RENDERTARGET) )) {
+        if(IWineD3DSurfaceImpl_BltOverride(This, DestRect, SrcSurface, SrcRect, Flags, DDBltFx) == WINED3D_OK) return WINED3D_OK;
+    }
+
+    /* For the rest call the X11 surface implementation.
+     * For RenderTargets this should be implemented OpenGL accelerated in BltOverride,
+     * other Blts are rather rare
+     */
+    return IWineGDISurfaceImpl_Blt(iface, DestRect, SrcSurface, SrcRect, Flags, DDBltFx);
+}
+
 HRESULT WINAPI IWineD3DSurfaceImpl_GetBltStatus(IWineD3DSurface *iface, DWORD Flags) {
     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
     TRACE("(%p)->(%lx)\n", This, Flags);
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index e562f416ed36ccb01bbf08ee518a90dc92276865..9493fd2b3efe0bb2f51f952f8fd0d0d8ad522c4c 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -2331,3 +2331,133 @@ BOOL isFourcc(WINED3DFORMAT fmt) {
            (fmt == WINED3DFMT_G8R8_G8B8) ||
            (fmt == WINED3DFMT_R8G8_B8G8);
 }
+
+/***********************************************************************
+ * CalculateTexRect
+ *
+ * Calculates the dimensions of the opengl texture used for blits.
+ * Handled oversized opengl textures and updates the source rectangle
+ * accordingly
+ *
+ * Params:
+ *  This: Surface to operate on
+ *  Rect: Requested rectangle
+ *
+ * Returns:
+ *  TRUE if the texture part can be loaded,
+ *  FALSE otherwise
+ *
+ *********************************************************************/
+#define GLINFO_LOCATION ((IWineD3DImpl *)(This->resource.wineD3DDevice->wineD3D))->gl_info
+
+BOOL CalculateTexRect(IWineD3DSurfaceImpl *This, RECT *Rect, float glTexCoord[4]) {
+    int x1 = Rect->left, x2 = Rect->right;
+    int y1 = Rect->top, y2 = Rect->bottom;
+    GLint maxSize = GL_LIMITS(texture_size);
+
+    TRACE("(%p)->(%ld,%ld)-(%ld,%ld)\n", This,
+          Rect->left, Rect->top, Rect->right, Rect->bottom);
+
+    /* The sizes might be reversed */
+    if(Rect->left > Rect->right) {
+        x1 = Rect->right;
+        x2 = Rect->left;
+    }
+    if(Rect->top > Rect->bottom) {
+        y1 = Rect->bottom;
+        y2 = Rect->top;
+    }
+
+    /* No oversized texture? This is easy */
+    if(!(This->Flags & SFLAG_OVERSIZE)) {
+        /* Which rect from the texture do I need? */
+        glTexCoord[0] = (float) Rect->left / (float) This->pow2Width;
+        glTexCoord[2] = (float) Rect->top / (float) This->pow2Height;
+        glTexCoord[1] = (float) Rect->right / (float) This->pow2Width;
+        glTexCoord[3] = (float) Rect->bottom / (float) This->pow2Height;
+
+        return TRUE;
+    } else {
+        /* Check if we can succeed at all */
+        if( (x2 - x1) > maxSize ||
+            (y2 - y1) > maxSize ) {
+            TRACE("Requested rectangle is too large for gl\n");
+            return FALSE;
+        }
+
+        /* A part of the texture has to be picked. First, check if
+         * some texture part is loaded already, if yes try to re-use it.
+         * If the texture is dirty, or the part can't be used,
+         * re-position the part to load
+         */
+        if(!(This->Flags & SFLAG_DIRTY)) {
+            if(This->glRect.left <= x1 && This->glRect.right >= x2 &&
+               This->glRect.top <= y1 && This->glRect.bottom >= x2 ) {
+                /* Ok, the rectangle is ok, re-use it */
+                TRACE("Using existing gl Texture\n");
+            } else {
+                /* Rectangle is not ok, dirtify the texture to reload it */
+                TRACE("Dirtifying texture to force reload\n");
+                This->Flags |= SFLAG_DIRTY;
+            }
+        }
+
+        /* Now if we are dirty(no else if!) */
+        if(This->Flags & SFLAG_DIRTY) {
+            /* Set the new rectangle. Use the following strategy:
+             * 1) Use as big textures as possible.
+             * 2) Place the texture part in the way that the requested
+             *    part is in the middle of the texture(well, almost)
+             * 3) If the texture is moved over the edges of the
+             *    surface, replace it nicely
+             * 4) If the coord is not limiting the texture size,
+             *    use the whole size
+             */
+            if((This->pow2Width) > maxSize) {
+                This->glRect.left = x1 - maxSize / 2;
+                if(This->glRect.left < 0) {
+                    This->glRect.left = 0;
+                }
+                This->glRect.right = This->glRect.left + maxSize;
+                if(This->glRect.right > This->currentDesc.Width) {
+                    This->glRect.right = This->currentDesc.Width;
+                    This->glRect.left = This->glRect.right - maxSize;
+                }
+            } else {
+                This->glRect.left = 0;
+                This->glRect.right = This->pow2Width;
+            }
+
+            if(This->pow2Height > maxSize) {
+                This->glRect.top = x1 - GL_LIMITS(texture_size) / 2;
+                if(This->glRect.top < 0) This->glRect.top = 0;
+                This->glRect.bottom = This->glRect.left + maxSize;
+                if(This->glRect.bottom > This->currentDesc.Height) {
+                    This->glRect.bottom = This->currentDesc.Height;
+                    This->glRect.top = This->glRect.bottom - maxSize;
+                }
+            } else {
+                This->glRect.top = 0;
+                This->glRect.bottom = This->pow2Height;
+            }
+            TRACE("(%p): Using rect (%ld,%ld)-(%ld,%ld)\n", This,
+                   This->glRect.left, This->glRect.top, This->glRect.right, This->glRect.bottom);
+        }
+
+        /* Re-calculate the rect to draw */
+        Rect->left -= This->glRect.left;
+        Rect->right -= This->glRect.left;
+        Rect->top -= This->glRect.top;
+        Rect->bottom -= This->glRect.top;
+
+        /* Get the gl coordinates. The gl rectangle is a power of 2, eighter the max size,
+         * or the pow2Width / pow2Height of the surface
+         */
+        glTexCoord[0] = (float) Rect->left / (float) (This->glRect.right - This->glRect.left);
+        glTexCoord[2] = (float) Rect->top / (float) (This->glRect.bottom - This->glRect.top);
+        glTexCoord[1] = (float) Rect->right / (float) (This->glRect.right - This->glRect.left);
+        glTexCoord[3] = (float) Rect->bottom / (float) (This->glRect.bottom - This->glRect.top);
+    }
+    return TRUE;
+}
+#undef GLINFO_LOCATION
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 50ab11550460bcb69392ed08bb0f33b85ad737fd..13fd3eab3be0b8694d01344907bc670df57d9efa 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -930,7 +930,7 @@ HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface);
 #define SFLAG_DYNLOCK     0x0800 /* Surface is often locked by the app */
 #define SFLAG_DYNCHANGE   0x1800 /* Surface contents are changed very often, implies DYNLOCK */
 #define SFLAG_DCINUSE     0x2000 /* Set between GetDC and ReleaseDC calls */
-#define SFLAG_NEWDC       0x4000 /* To inform LockRect about a new dc */
+#define SFLAG_GLDIRTY     0x4000 /* The opengl texture is more up to date than the surface mem */
 #define SFLAG_LOST        0x8000 /* Surface lost flag for DDraw */
 
 /* In some conditions the surface memory must not be freed:
@@ -952,6 +952,8 @@ HRESULT WINAPI IWineD3DSurfaceImpl_RealizePalette(IWineD3DSurface *iface);
                           SFLAG_DYNLOCK    | \
                           SFLAG_DYNCHANGE    )
 
+BOOL CalculateTexRect(IWineD3DSurfaceImpl *This, RECT *Rect, float glTexCoord[4]);
+
 /*****************************************************************************
  * IWineD3DVertexDeclaration implementation structure
  */