wined3d: Move upsideDown calculation to blit implementation.

This commit is contained in:
Roderick Colenbrander 2010-04-01 23:58:49 +02:00 committed by Alexandre Julliard
parent 29937272cb
commit ff82e66a69
3 changed files with 53 additions and 46 deletions

View File

@ -5683,7 +5683,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice
}
void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, const RECT *src_rect_in,
IWineD3DSurface *dst_surface, const RECT *dst_rect_in, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip)
IWineD3DSurface *dst_surface, const RECT *dst_rect_in, const WINED3DTEXTUREFILTERTYPE filter)
{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */
@ -5693,8 +5693,8 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, const
POINT offset = {0, 0};
RECT src_rect, dst_rect;
TRACE("(%p) : src_surface %p, src_rect_in %p, dst_surface %p, dst_rect_in %p, filter %s (0x%08x), flip %u\n",
This, src_surface, src_rect_in, dst_surface, dst_rect_in, debug_d3dtexturefiltertype(filter), filter, flip);
TRACE("(%p) : src_surface %p, src_rect_in %p, dst_surface %p, dst_rect_in %p, filter %s (0x%08x)\n",
This, src_surface, src_rect_in, dst_surface, dst_rect_in, debug_d3dtexturefiltertype(filter), filter);
TRACE("src_rect_in %s\n", wine_dbgstr_rect(src_rect_in));
TRACE("dst_rect_in %s\n", wine_dbgstr_rect(dst_rect_in));
@ -5807,15 +5807,9 @@ void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, const
glDisable(GL_SCISSOR_TEST);
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
if (flip) {
gl_info->fbo_ops.glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom,
dst_rect.left, dst_rect.bottom, dst_rect.right, dst_rect.top, mask, gl_filter);
checkGLcall("glBlitFramebuffer()");
} else {
gl_info->fbo_ops.glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom,
dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom, mask, gl_filter);
checkGLcall("glBlitFramebuffer()");
}
gl_info->fbo_ops.glBlitFramebuffer(src_rect.left, src_rect.top, src_rect.right, src_rect.bottom,
dst_rect.left, dst_rect.top, dst_rect.right, dst_rect.bottom, mask, gl_filter);
checkGLcall("glBlitFramebuffer()");
LEAVE_GL();

View File

@ -3409,14 +3409,25 @@ static HRESULT WINAPI IWineD3DSurfaceImpl_Flip(IWineD3DSurface *iface, IWineD3DS
* with single pixel copy calls
*/
static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3DSurface *SrcSurface,
const RECT *src_rect, const RECT *dst_rect, BOOL upsidedown, WINED3DTEXTUREFILTERTYPE Filter)
const RECT *src_rect, const RECT *dst_rect_in, WINED3DTEXTUREFILTERTYPE Filter)
{
IWineD3DDeviceImpl *myDevice = This->resource.device;
float xrel, yrel;
UINT row;
IWineD3DSurfaceImpl *Src = (IWineD3DSurfaceImpl *) SrcSurface;
struct wined3d_context *context;
BOOL upsidedown = FALSE;
RECT dst_rect = *dst_rect_in;
/* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag
* glCopyTexSubImage is a bit picky about the parameters we pass to it
*/
if(dst_rect.top > dst_rect.bottom) {
UINT tmp = dst_rect.bottom;
dst_rect.bottom = dst_rect.top;
dst_rect.top = tmp;
upsidedown = TRUE;
}
context = context_acquire(myDevice, SrcSurface, CTXUSAGE_BLIT);
surface_internal_preload((IWineD3DSurface *) This, SRGB_RGB);
@ -3436,8 +3447,8 @@ static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3D
}
checkGLcall("glReadBuffer");
xrel = (float) (src_rect->right - src_rect->left) / (float) (dst_rect->right - dst_rect->left);
yrel = (float) (src_rect->bottom - src_rect->top) / (float) (dst_rect->bottom - dst_rect->top);
xrel = (float) (src_rect->right - src_rect->left) / (float) (dst_rect.right - dst_rect.left);
yrel = (float) (src_rect->bottom - src_rect->top) / (float) (dst_rect.bottom - dst_rect.top);
if ((xrel - 1.0f < -eps) || (xrel - 1.0f > eps))
{
@ -3460,18 +3471,18 @@ static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3D
/* Upside down copy without stretching is nice, one glCopyTexSubImage call will do */
glCopyTexSubImage2D(This->texture_target, This->texture_level,
dst_rect->left /*xoffset */, dst_rect->top /* y offset */,
dst_rect.left /*xoffset */, dst_rect.top /* y offset */,
src_rect->left, Src->currentDesc.Height - src_rect->bottom,
dst_rect->right - dst_rect->left, dst_rect->bottom - dst_rect->top);
dst_rect.right - dst_rect.left, dst_rect.bottom - dst_rect.top);
} else {
UINT yoffset = Src->currentDesc.Height - src_rect->top + dst_rect->top - 1;
UINT yoffset = Src->currentDesc.Height - src_rect->top + dst_rect.top - 1;
/* I have to process this row by row to swap the image,
* otherwise it would be upside down, so stretching in y direction
* doesn't cost extra time
*
* However, stretching in x direction can be avoided if not necessary
*/
for(row = dst_rect->top; row < dst_rect->bottom; row++) {
for(row = dst_rect.top; row < dst_rect.bottom; row++) {
if ((xrel - 1.0f < -eps) || (xrel - 1.0f > eps))
{
/* Well, that stuff works, but it's very slow.
@ -3479,15 +3490,15 @@ static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3D
*/
UINT col;
for(col = dst_rect->left; col < dst_rect->right; col++) {
for(col = dst_rect.left; col < dst_rect.right; col++) {
glCopyTexSubImage2D(This->texture_target, This->texture_level,
dst_rect->left + col /* x offset */, row /* y offset */,
dst_rect.left + col /* x offset */, row /* y offset */,
src_rect->left + col * xrel, yoffset - (int) (row * yrel), 1, 1);
}
} else {
glCopyTexSubImage2D(This->texture_target, This->texture_level,
dst_rect->left /* x offset */, row /* y offset */,
src_rect->left, yoffset - (int) (row * yrel), dst_rect->right-dst_rect->left, 1);
dst_rect.left /* x offset */, row /* y offset */,
src_rect->left, yoffset - (int) (row * yrel), dst_rect.right - dst_rect.left, 1);
}
}
}
@ -3504,8 +3515,8 @@ static inline void fb_copy_to_texture_direct(IWineD3DSurfaceImpl *This, IWineD3D
/* Uses the hardware to stretch and flip the image */
static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWineD3DSurface *SrcSurface,
IWineD3DSwapChainImpl *swapchain, const RECT *src_rect, const RECT *dst_rect,
BOOL upsidedown, WINED3DTEXTUREFILTERTYPE Filter)
IWineD3DSwapChainImpl *swapchain, const RECT *src_rect, const RECT *dst_rect_in,
WINED3DTEXTUREFILTERTYPE Filter)
{
IWineD3DDeviceImpl *myDevice = This->resource.device;
GLuint src, backup = 0;
@ -3518,6 +3529,8 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine
GLenum texture_target;
BOOL noBackBufferBackup;
BOOL src_offscreen;
BOOL upsidedown = FALSE;
RECT dst_rect = *dst_rect_in;
TRACE("Using hwstretch blit\n");
/* Activate the Proper context for reading from the source surface, set it up for blitting */
@ -3567,6 +3580,16 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine
Src->Flags &= ~SFLAG_INTEXTURE;
}
/* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag
* glCopyTexSubImage is a bit picky about the parameters we pass to it
*/
if(dst_rect.top > dst_rect.bottom) {
UINT tmp = dst_rect.bottom;
dst_rect.bottom = dst_rect.top;
dst_rect.top = tmp;
upsidedown = TRUE;
}
if (src_offscreen)
{
TRACE("Reading from an offscreen target\n");
@ -3666,15 +3689,15 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine
/* top left */
glTexCoord2f(left, top);
glVertex2i(0, fbheight - dst_rect->bottom - dst_rect->top);
glVertex2i(0, fbheight - dst_rect.bottom - dst_rect.top);
/* top right */
glTexCoord2f(right, top);
glVertex2i(dst_rect->right - dst_rect->left, fbheight - dst_rect->bottom - dst_rect->top);
glVertex2i(dst_rect.right - dst_rect.left, fbheight - dst_rect.bottom - dst_rect.top);
/* bottom right */
glTexCoord2f(right, bottom);
glVertex2i(dst_rect->right - dst_rect->left, fbheight);
glVertex2i(dst_rect.right - dst_rect.left, fbheight);
glEnd();
checkGLcall("glEnd and previous");
@ -3690,9 +3713,9 @@ static inline void fb_copy_to_texture_hwstretch(IWineD3DSurfaceImpl *This, IWine
checkGLcall("glBindTexture");
glCopyTexSubImage2D(texture_target,
0,
dst_rect->left, dst_rect->top, /* xoffset, yoffset */
dst_rect.left, dst_rect.top, /* xoffset, yoffset */
0, 0, /* We blitted the image to the origin */
dst_rect->right - dst_rect->left, dst_rect->bottom - dst_rect->top);
dst_rect.right - dst_rect.left, dst_rect.bottom - dst_rect.top);
checkGLcall("glCopyTexSubImage2D");
if(drawBuffer == GL_BACK) {
@ -3917,7 +3940,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const
if((srcSwapchain || SrcSurface == myDevice->render_targets[0]) && !dstSwapchain) {
/* Blit from render target to texture */
BOOL upsideDown = FALSE, stretchx;
BOOL stretchx;
BOOL paletteOverride = FALSE;
if(Flags & (WINEDDBLT_KEYSRC | WINEDDBLT_KEYSRCOVERRIDE)) {
@ -3926,16 +3949,6 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const
/* Destination color key is checked above */
}
/* Make sure that the top pixel is always above the bottom pixel, and keep a separate upside down flag
* glCopyTexSubImage is a bit picky about the parameters we pass to it
*/
if(dst_rect.top > dst_rect.bottom) {
UINT tmp = dst_rect.bottom;
dst_rect.bottom = dst_rect.top;
dst_rect.top = tmp;
upsideDown = TRUE;
}
if(dst_rect.right - dst_rect.left != src_rect.right - src_rect.left) {
stretchx = TRUE;
} else {
@ -3971,14 +3984,14 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const
&& surface_can_stretch_rect(Src, This))
{
stretch_rect_fbo((IWineD3DDevice *)myDevice, SrcSurface, &src_rect,
(IWineD3DSurface *)This, &dst_rect, Filter, upsideDown);
(IWineD3DSurface *)This, &dst_rect, Filter);
} else if((!stretchx) || dst_rect.right - dst_rect.left > Src->currentDesc.Width ||
dst_rect.bottom - dst_rect.top > Src->currentDesc.Height) {
TRACE("No stretching in x direction, using direct framebuffer -> texture copy\n");
fb_copy_to_texture_direct(This, SrcSurface, &src_rect, &dst_rect, upsideDown, Filter);
fb_copy_to_texture_direct(This, SrcSurface, &src_rect, &dst_rect, Filter);
} else {
TRACE("Using hardware stretching to flip / stretch the texture\n");
fb_copy_to_texture_hwstretch(This, SrcSurface, srcSwapchain, &src_rect, &dst_rect, upsideDown, Filter);
fb_copy_to_texture_hwstretch(This, SrcSurface, srcSwapchain, &src_rect, &dst_rect, Filter);
}
/* Clear the palette as the surface didn't have a palette attached, it would confuse GetPalette and other calls */
@ -4024,7 +4037,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, const
* contents are never upside down
*/
stretch_rect_fbo((IWineD3DDevice *)myDevice, SrcSurface, &src_rect,
(IWineD3DSurface *)This, &dst_rect, Filter, FALSE);
(IWineD3DSurface *)This, &dst_rect, Filter);
/* Clear the palette as the surface didn't have a palette attached, it would confuse GetPalette and other calls */
if(paletteOverride)

View File

@ -3033,7 +3033,7 @@ static inline BOOL use_ps(IWineD3DStateBlockImpl *stateblock)
void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface,
const RECT *src_rect, IWineD3DSurface *dst_surface, const RECT *dst_rect,
const WINED3DTEXTUREFILTERTYPE filter, BOOL flip) DECLSPEC_HIDDEN;
const WINED3DTEXTUREFILTERTYPE filter) DECLSPEC_HIDDEN;
/* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */
#define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL"