wined3d: Use the framebuffer blit extension to implement StretchRect.
This commit is contained in:
parent
70dd7ced99
commit
75e91fa409
@ -181,6 +181,12 @@ static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
|
|||||||
if (This->fbo) {
|
if (This->fbo) {
|
||||||
GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo));
|
GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo));
|
||||||
}
|
}
|
||||||
|
if (This->src_fbo) {
|
||||||
|
GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->src_fbo));
|
||||||
|
}
|
||||||
|
if (This->dst_fbo) {
|
||||||
|
GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->dst_fbo));
|
||||||
|
}
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, This->render_targets);
|
HeapFree(GetProcessHeap(), 0, This->render_targets);
|
||||||
HeapFree(GetProcessHeap(), 0, This->fbo_color_attachments);
|
HeapFree(GetProcessHeap(), 0, This->fbo_color_attachments);
|
||||||
@ -5242,6 +5248,77 @@ void apply_fbo_state(IWineD3DDevice *iface) {
|
|||||||
check_fbo_status(iface);
|
check_fbo_status(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL is_onscreen(IWineD3DSurface *target) {
|
||||||
|
HRESULT hr;
|
||||||
|
void *tmp;
|
||||||
|
|
||||||
|
hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, &tmp);
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
IWineD3DSwapChain_Release((IUnknown *)tmp);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, const WINED3DRECT *src_rect,
|
||||||
|
IWineD3DSurface *dst_surface, const WINED3DRECT *dst_rect, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip) {
|
||||||
|
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||||
|
GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */
|
||||||
|
GLenum gl_filter;
|
||||||
|
|
||||||
|
TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x)\n",
|
||||||
|
This, src_surface, src_rect, dst_surface, dst_rect, debug_d3dtexturefiltertype(filter), filter);
|
||||||
|
|
||||||
|
switch (filter) {
|
||||||
|
case WINED3DTEXF_LINEAR:
|
||||||
|
gl_filter = GL_LINEAR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
FIXME("Unsupported filter mode %s (0x%08x)\n", debug_d3dtexturefiltertype(filter), filter);
|
||||||
|
case WINED3DTEXF_NONE:
|
||||||
|
case WINED3DTEXF_POINT:
|
||||||
|
gl_filter = GL_NEAREST;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attach src surface to src fbo */
|
||||||
|
if (is_onscreen(src_surface)) {
|
||||||
|
GL_EXTCALL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0));
|
||||||
|
flip = !flip;
|
||||||
|
} else {
|
||||||
|
IWineD3DSurface_PreLoad(src_surface);
|
||||||
|
bind_fbo(iface, GL_READ_FRAMEBUFFER_EXT, &This->src_fbo);
|
||||||
|
attach_surface_fbo(This, GL_READ_FRAMEBUFFER_EXT, 0, src_surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attach dst surface to dst fbo */
|
||||||
|
if (is_onscreen(dst_surface)) {
|
||||||
|
GL_EXTCALL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0));
|
||||||
|
flip = !flip;
|
||||||
|
} else {
|
||||||
|
IWineD3DSurface_PreLoad(dst_surface);
|
||||||
|
bind_fbo(iface, GL_DRAW_FRAMEBUFFER_EXT, &This->dst_fbo);
|
||||||
|
attach_surface_fbo(This, GL_DRAW_FRAMEBUFFER_EXT, 0, dst_surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flip) {
|
||||||
|
GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
|
||||||
|
dst_rect->x1, dst_rect->y2, dst_rect->x2, dst_rect->y1, mask, gl_filter));
|
||||||
|
} else {
|
||||||
|
GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
|
||||||
|
dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2, mask, gl_filter));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (This->render_offscreen) {
|
||||||
|
bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
|
||||||
|
} else {
|
||||||
|
GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||||
|
checkGLcall("glBindFramebuffer()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
|
static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
|
||||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||||
WINED3DVIEWPORT viewport;
|
WINED3DVIEWPORT viewport;
|
||||||
|
@ -2759,8 +2759,7 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Blt is a pretty powerful call, while glCopyTexSubImage2D is not. glCopyTexSubImage cannot
|
/* Blt is a pretty powerful call, while glCopyTexSubImage2D is not. glCopyTexSubImage cannot
|
||||||
* flip the image nor scale it. If GL_EXT_framebuffer_blit is available it can be used(hopefully,
|
* flip the image nor scale it.
|
||||||
* not implemented by now). Otherwise:
|
|
||||||
*
|
*
|
||||||
* -> If the app asks for a unscaled, upside down copy, just perform one glCopyTexSubImage2D call
|
* -> If the app asks for a unscaled, upside down copy, just perform one glCopyTexSubImage2D call
|
||||||
* -> If the app wants a image width an unscaled width, copy it line per line
|
* -> If the app wants a image width an unscaled width, copy it line per line
|
||||||
@ -2769,9 +2768,14 @@ static HRESULT IWineD3DSurfaceImpl_BltOverride(IWineD3DSurfaceImpl *This, RECT *
|
|||||||
* back buffer. This is slower than reading line per line, thus not used for flipping
|
* back buffer. This is slower than reading line per line, thus not used for flipping
|
||||||
* -> If the app wants a scaled image with a dest rect that is bigger than the fb, it has to be copied
|
* -> If the app wants a scaled image with a dest rect that is bigger than the fb, it has to be copied
|
||||||
* pixel by pixel
|
* pixel by pixel
|
||||||
|
*
|
||||||
|
* If EXT_framebuffer_blit is supported that can be used instead. Note that EXT_framebuffer_blit implies
|
||||||
|
* FBO support, so it doesn't really make sense to try and make it work with different offscreen rendering
|
||||||
|
* backends.
|
||||||
*/
|
*/
|
||||||
if(FALSE /* GL_SUPPORT(EXT_FRAMEBUFFER_BLIT) */) {
|
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO && GL_SUPPORT(EXT_FRAMEBUFFER_BLIT)) {
|
||||||
TRACE("Using GL_EXT_framebuffer_blit for copying\n");
|
stretch_rect_fbo((IWineD3DDevice *)myDevice, SrcSurface, &srect,
|
||||||
|
(IWineD3DSurface *)This, &rect, Filter, upsideDown);
|
||||||
} else if((!stretchx) || rect.x2 - rect.x1 > Src->currentDesc.Width ||
|
} else if((!stretchx) || rect.x2 - rect.x1 > Src->currentDesc.Width ||
|
||||||
rect.y2 - rect.y1 > Src->currentDesc.Height) {
|
rect.y2 - rect.y1 > Src->currentDesc.Height) {
|
||||||
TRACE("No stretching in x direction, using direct framebuffer -> texture copy\n");
|
TRACE("No stretching in x direction, using direct framebuffer -> texture copy\n");
|
||||||
|
@ -674,6 +674,8 @@ struct IWineD3DDeviceImpl
|
|||||||
BOOL render_offscreen;
|
BOOL render_offscreen;
|
||||||
WINED3D_DEPTHCOPYSTATE depth_copy_state;
|
WINED3D_DEPTHCOPYSTATE depth_copy_state;
|
||||||
GLuint fbo;
|
GLuint fbo;
|
||||||
|
GLuint src_fbo;
|
||||||
|
GLuint dst_fbo;
|
||||||
GLenum *draw_buffers;
|
GLenum *draw_buffers;
|
||||||
|
|
||||||
/* Cursor management */
|
/* Cursor management */
|
||||||
@ -1969,4 +1971,7 @@ static inline BOOL use_ps(IWineD3DDeviceImpl *device) {
|
|||||||
&& ((IWineD3DPixelShaderImpl *)device->stateBlock->pixelShader)->baseShader.function);
|
&& ((IWineD3DPixelShaderImpl *)device->stateBlock->pixelShader)->baseShader.function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, const WINED3DRECT *src_rect,
|
||||||
|
IWineD3DSurface *dst_surface, const WINED3DRECT *dst_rect, WINED3DTEXTUREFILTERTYPE filter, BOOL flip);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user