wined3d: Move device_clear_render_targets() to texture.c.
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
cd94aa8fa8
commit
ee8e4d2010
|
@ -257,251 +257,6 @@ void device_context_remove(struct wined3d_device *device, struct wined3d_context
|
||||||
device->contexts = new_array;
|
device->contexts = new_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL is_full_clear(const struct wined3d_texture *texture, unsigned int sub_resource_idx,
|
|
||||||
const RECT *draw_rect, const RECT *clear_rect)
|
|
||||||
{
|
|
||||||
unsigned int width, height, level;
|
|
||||||
|
|
||||||
level = sub_resource_idx % texture->level_count;
|
|
||||||
width = wined3d_texture_get_level_width(texture, level);
|
|
||||||
height = wined3d_texture_get_level_height(texture, level);
|
|
||||||
|
|
||||||
/* partial draw rect */
|
|
||||||
if (draw_rect->left || draw_rect->top || draw_rect->right < width || draw_rect->bottom < height)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* partial clear rect */
|
|
||||||
if (clear_rect && (clear_rect->left > 0 || clear_rect->top > 0
|
|
||||||
|| clear_rect->right < width || clear_rect->bottom < height))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, const struct wined3d_fb_state *fb,
|
|
||||||
UINT rect_count, const RECT *clear_rect, const RECT *draw_rect, DWORD flags, const struct wined3d_color *color,
|
|
||||||
float depth, DWORD stencil)
|
|
||||||
{
|
|
||||||
struct wined3d_rendertarget_view *rtv = rt_count ? fb->render_targets[0] : NULL;
|
|
||||||
struct wined3d_rendertarget_view *dsv = fb->depth_stencil;
|
|
||||||
const struct wined3d_state *state = &device->cs->state;
|
|
||||||
struct wined3d_texture *depth_stencil = NULL;
|
|
||||||
const struct wined3d_gl_info *gl_info;
|
|
||||||
struct wined3d_context_gl *context_gl;
|
|
||||||
struct wined3d_texture *target = NULL;
|
|
||||||
UINT drawable_width, drawable_height;
|
|
||||||
struct wined3d_color colour_srgb;
|
|
||||||
struct wined3d_context *context;
|
|
||||||
GLbitfield clear_mask = 0;
|
|
||||||
BOOL render_offscreen;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
if (rtv && rtv->resource->type != WINED3D_RTYPE_BUFFER)
|
|
||||||
{
|
|
||||||
target = texture_from_resource(rtv->resource);
|
|
||||||
context = context_acquire(device, target, rtv->sub_resource_idx);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
context = context_acquire(device, NULL, 0);
|
|
||||||
}
|
|
||||||
context_gl = wined3d_context_gl(context);
|
|
||||||
|
|
||||||
if (dsv && dsv->resource->type != WINED3D_RTYPE_BUFFER)
|
|
||||||
depth_stencil = texture_from_resource(dsv->resource);
|
|
||||||
|
|
||||||
if (!context_gl->valid)
|
|
||||||
{
|
|
||||||
context_release(context);
|
|
||||||
WARN("Invalid context, skipping clear.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
gl_info = context_gl->gl_info;
|
|
||||||
|
|
||||||
/* When we're clearing parts of the drawable, make sure that the target surface is well up to date in the
|
|
||||||
* drawable. After the clear we'll mark the drawable up to date, so we have to make sure that this is true
|
|
||||||
* for the cleared parts, and the untouched parts.
|
|
||||||
*
|
|
||||||
* If we're clearing the whole target there is no need to copy it into the drawable, it will be overwritten
|
|
||||||
* anyway. If we're not clearing the color buffer we don't have to copy either since we're not going to set
|
|
||||||
* the drawable up to date. We have to check all settings that limit the clear area though. Do not bother
|
|
||||||
* checking all this if the dest surface is in the drawable anyway. */
|
|
||||||
for (i = 0; i < rt_count; ++i)
|
|
||||||
{
|
|
||||||
struct wined3d_rendertarget_view *rtv = fb->render_targets[i];
|
|
||||||
|
|
||||||
if (rtv && rtv->format->id != WINED3DFMT_NULL)
|
|
||||||
{
|
|
||||||
struct wined3d_texture *rt = wined3d_texture_from_resource(rtv->resource);
|
|
||||||
|
|
||||||
if (flags & WINED3DCLEAR_TARGET && !is_full_clear(rt, rtv->sub_resource_idx,
|
|
||||||
draw_rect, rect_count ? clear_rect : NULL))
|
|
||||||
wined3d_texture_load_location(rt, rtv->sub_resource_idx, context, rtv->resource->draw_binding);
|
|
||||||
else
|
|
||||||
wined3d_texture_prepare_location(rt, rtv->sub_resource_idx, context, rtv->resource->draw_binding);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target)
|
|
||||||
{
|
|
||||||
render_offscreen = context->render_offscreen;
|
|
||||||
wined3d_rendertarget_view_get_drawable_size(rtv, context, &drawable_width, &drawable_height);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unsigned int ds_level = dsv->sub_resource_idx % depth_stencil->level_count;
|
|
||||||
|
|
||||||
render_offscreen = TRUE;
|
|
||||||
drawable_width = wined3d_texture_get_level_pow2_width(depth_stencil, ds_level);
|
|
||||||
drawable_height = wined3d_texture_get_level_pow2_height(depth_stencil, ds_level);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depth_stencil)
|
|
||||||
{
|
|
||||||
DWORD ds_location = render_offscreen ? dsv->resource->draw_binding : WINED3D_LOCATION_DRAWABLE;
|
|
||||||
struct wined3d_texture *ds = wined3d_texture_from_resource(dsv->resource);
|
|
||||||
|
|
||||||
if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)
|
|
||||||
&& !is_full_clear(ds, dsv->sub_resource_idx, draw_rect, rect_count ? clear_rect : NULL))
|
|
||||||
wined3d_texture_load_location(ds, dsv->sub_resource_idx, context, ds_location);
|
|
||||||
else
|
|
||||||
wined3d_texture_prepare_location(ds, dsv->sub_resource_idx, context, ds_location);
|
|
||||||
|
|
||||||
if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
|
|
||||||
{
|
|
||||||
wined3d_texture_validate_location(ds, dsv->sub_resource_idx, ds_location);
|
|
||||||
wined3d_texture_invalidate_location(ds, dsv->sub_resource_idx, ~ds_location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wined3d_context_gl_apply_clear_state(context_gl, state, rt_count, fb))
|
|
||||||
{
|
|
||||||
context_release(context);
|
|
||||||
WARN("Failed to apply clear state, skipping clear.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Only set the values up once, as they are not changing. */
|
|
||||||
if (flags & WINED3DCLEAR_STENCIL)
|
|
||||||
{
|
|
||||||
if (gl_info->supported[EXT_STENCIL_TWO_SIDE])
|
|
||||||
{
|
|
||||||
gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
|
|
||||||
context_invalidate_state(context, STATE_RENDER(WINED3D_RS_TWOSIDEDSTENCILMODE));
|
|
||||||
}
|
|
||||||
gl_info->gl_ops.gl.p_glStencilMask(~0U);
|
|
||||||
context_invalidate_state(context, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK));
|
|
||||||
gl_info->gl_ops.gl.p_glClearStencil(stencil);
|
|
||||||
checkGLcall("glClearStencil");
|
|
||||||
clear_mask = clear_mask | GL_STENCIL_BUFFER_BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & WINED3DCLEAR_ZBUFFER)
|
|
||||||
{
|
|
||||||
gl_info->gl_ops.gl.p_glDepthMask(GL_TRUE);
|
|
||||||
context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ZWRITEENABLE));
|
|
||||||
gl_info->gl_ops.gl.p_glClearDepth(depth);
|
|
||||||
checkGLcall("glClearDepth");
|
|
||||||
clear_mask = clear_mask | GL_DEPTH_BUFFER_BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & WINED3DCLEAR_TARGET)
|
|
||||||
{
|
|
||||||
for (i = 0; i < rt_count; ++i)
|
|
||||||
{
|
|
||||||
struct wined3d_rendertarget_view *rtv = fb->render_targets[i];
|
|
||||||
struct wined3d_texture *texture;
|
|
||||||
|
|
||||||
if (!rtv)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (rtv->resource->type == WINED3D_RTYPE_BUFFER)
|
|
||||||
{
|
|
||||||
FIXME("Not supported on buffer resources.\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
texture = texture_from_resource(rtv->resource);
|
|
||||||
wined3d_texture_validate_location(texture, rtv->sub_resource_idx, rtv->resource->draw_binding);
|
|
||||||
wined3d_texture_invalidate_location(texture, rtv->sub_resource_idx, ~rtv->resource->draw_binding);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] && needs_srgb_write(context->d3d_info, state, fb))
|
|
||||||
{
|
|
||||||
if (rt_count > 1)
|
|
||||||
WARN("Clearing multiple sRGB render targets without GL_ARB_framebuffer_sRGB "
|
|
||||||
"support, this might cause graphical issues.\n");
|
|
||||||
|
|
||||||
wined3d_colour_srgb_from_linear(&colour_srgb, color);
|
|
||||||
color = &colour_srgb;
|
|
||||||
}
|
|
||||||
|
|
||||||
gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
|
||||||
context_invalidate_state(context, STATE_BLEND);
|
|
||||||
gl_info->gl_ops.gl.p_glClearColor(color->r, color->g, color->b, color->a);
|
|
||||||
checkGLcall("glClearColor");
|
|
||||||
clear_mask = clear_mask | GL_COLOR_BUFFER_BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rect_count)
|
|
||||||
{
|
|
||||||
if (render_offscreen)
|
|
||||||
{
|
|
||||||
gl_info->gl_ops.gl.p_glScissor(draw_rect->left, draw_rect->top,
|
|
||||||
draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gl_info->gl_ops.gl.p_glScissor(draw_rect->left, drawable_height - draw_rect->bottom,
|
|
||||||
draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top);
|
|
||||||
}
|
|
||||||
gl_info->gl_ops.gl.p_glClear(clear_mask);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RECT current_rect;
|
|
||||||
|
|
||||||
/* Now process each rect in turn. */
|
|
||||||
for (i = 0; i < rect_count; ++i)
|
|
||||||
{
|
|
||||||
/* Note that GL uses lower left, width/height. */
|
|
||||||
IntersectRect(¤t_rect, draw_rect, &clear_rect[i]);
|
|
||||||
|
|
||||||
TRACE("clear_rect[%u] %s, current_rect %s.\n", i,
|
|
||||||
wine_dbgstr_rect(&clear_rect[i]),
|
|
||||||
wine_dbgstr_rect(¤t_rect));
|
|
||||||
|
|
||||||
/* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
|
|
||||||
* The rectangle is not cleared, no error is returned, but further rectangles are
|
|
||||||
* still cleared if they are valid. */
|
|
||||||
if (current_rect.left > current_rect.right || current_rect.top > current_rect.bottom)
|
|
||||||
{
|
|
||||||
TRACE("Rectangle with negative dimensions, ignoring.\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (render_offscreen)
|
|
||||||
{
|
|
||||||
gl_info->gl_ops.gl.p_glScissor(current_rect.left, current_rect.top,
|
|
||||||
current_rect.right - current_rect.left, current_rect.bottom - current_rect.top);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gl_info->gl_ops.gl.p_glScissor(current_rect.left, drawable_height - current_rect.bottom,
|
|
||||||
current_rect.right - current_rect.left, current_rect.bottom - current_rect.top);
|
|
||||||
}
|
|
||||||
gl_info->gl_ops.gl.p_glClear(clear_mask);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
context->scissor_rect_count = WINED3D_MAX_VIEWPORTS;
|
|
||||||
checkGLcall("clear");
|
|
||||||
|
|
||||||
if (flags & WINED3DCLEAR_TARGET && target->swapchain && target->swapchain->front_buffer == target)
|
|
||||||
gl_info->gl_ops.gl.p_glFlush();
|
|
||||||
|
|
||||||
context_release(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG CDECL wined3d_device_incref(struct wined3d_device *device)
|
ULONG CDECL wined3d_device_incref(struct wined3d_device *device)
|
||||||
{
|
{
|
||||||
ULONG refcount = InterlockedIncrement(&device->ref);
|
ULONG refcount = InterlockedIncrement(&device->ref);
|
||||||
|
|
|
@ -5176,6 +5176,254 @@ static bool ffp_blit_supported(enum wined3d_blit_op blit_op, const struct wined3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_full_clear(const struct wined3d_texture *texture, unsigned int sub_resource_idx,
|
||||||
|
const RECT *draw_rect, const RECT *clear_rect)
|
||||||
|
{
|
||||||
|
unsigned int width, height, level;
|
||||||
|
|
||||||
|
level = sub_resource_idx % texture->level_count;
|
||||||
|
width = wined3d_texture_get_level_width(texture, level);
|
||||||
|
height = wined3d_texture_get_level_height(texture, level);
|
||||||
|
|
||||||
|
/* partial draw rect */
|
||||||
|
if (draw_rect->left || draw_rect->top || draw_rect->right < width || draw_rect->bottom < height)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* partial clear rect */
|
||||||
|
if (clear_rect && (clear_rect->left > 0 || clear_rect->top > 0
|
||||||
|
|| clear_rect->right < width || clear_rect->bottom < height))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ffp_blitter_clear_rendertargets(struct wined3d_device *device, unsigned int rt_count,
|
||||||
|
const struct wined3d_fb_state *fb, unsigned int rect_count, const RECT *clear_rect, const RECT *draw_rect,
|
||||||
|
uint32_t flags, const struct wined3d_color *colour, float depth, unsigned int stencil)
|
||||||
|
{
|
||||||
|
struct wined3d_rendertarget_view *rtv = rt_count ? fb->render_targets[0] : NULL;
|
||||||
|
struct wined3d_rendertarget_view *dsv = fb->depth_stencil;
|
||||||
|
const struct wined3d_state *state = &device->cs->state;
|
||||||
|
struct wined3d_texture *depth_stencil = NULL;
|
||||||
|
unsigned int drawable_width, drawable_height;
|
||||||
|
const struct wined3d_gl_info *gl_info;
|
||||||
|
struct wined3d_context_gl *context_gl;
|
||||||
|
struct wined3d_texture *target = NULL;
|
||||||
|
struct wined3d_color colour_srgb;
|
||||||
|
struct wined3d_context *context;
|
||||||
|
GLbitfield clear_mask = 0;
|
||||||
|
bool render_offscreen;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (rtv && rtv->resource->type != WINED3D_RTYPE_BUFFER)
|
||||||
|
{
|
||||||
|
target = texture_from_resource(rtv->resource);
|
||||||
|
context = context_acquire(device, target, rtv->sub_resource_idx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context = context_acquire(device, NULL, 0);
|
||||||
|
}
|
||||||
|
context_gl = wined3d_context_gl(context);
|
||||||
|
|
||||||
|
if (dsv && dsv->resource->type != WINED3D_RTYPE_BUFFER)
|
||||||
|
depth_stencil = texture_from_resource(dsv->resource);
|
||||||
|
|
||||||
|
if (!context_gl->valid)
|
||||||
|
{
|
||||||
|
context_release(context);
|
||||||
|
WARN("Invalid context, skipping clear.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gl_info = context_gl->gl_info;
|
||||||
|
|
||||||
|
/* When we're clearing parts of the drawable, make sure that the target
|
||||||
|
* surface is well up to date in the drawable. After the clear we'll mark
|
||||||
|
* the drawable up to date, so we have to make sure that this is true for
|
||||||
|
* the cleared parts, and the untouched parts.
|
||||||
|
*
|
||||||
|
* If we're clearing the whole target there is no need to copy it into the
|
||||||
|
* drawable, it will be overwritten anyway. If we're not clearing the
|
||||||
|
* colour buffer we don't have to copy either since we're not going to set
|
||||||
|
* the drawable up to date. We have to check all settings that limit the
|
||||||
|
* clear area though. Do not bother checking all this if the destination
|
||||||
|
* surface is in the drawable anyway. */
|
||||||
|
for (i = 0; i < rt_count; ++i)
|
||||||
|
{
|
||||||
|
struct wined3d_rendertarget_view *rtv = fb->render_targets[i];
|
||||||
|
|
||||||
|
if (rtv && rtv->format->id != WINED3DFMT_NULL)
|
||||||
|
{
|
||||||
|
struct wined3d_texture *rt = wined3d_texture_from_resource(rtv->resource);
|
||||||
|
|
||||||
|
if (flags & WINED3DCLEAR_TARGET && !is_full_clear(rt, rtv->sub_resource_idx,
|
||||||
|
draw_rect, rect_count ? clear_rect : NULL))
|
||||||
|
wined3d_texture_load_location(rt, rtv->sub_resource_idx, context, rtv->resource->draw_binding);
|
||||||
|
else
|
||||||
|
wined3d_texture_prepare_location(rt, rtv->sub_resource_idx, context, rtv->resource->draw_binding);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target)
|
||||||
|
{
|
||||||
|
render_offscreen = context->render_offscreen;
|
||||||
|
wined3d_rendertarget_view_get_drawable_size(rtv, context, &drawable_width, &drawable_height);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int ds_level = dsv->sub_resource_idx % depth_stencil->level_count;
|
||||||
|
|
||||||
|
render_offscreen = true;
|
||||||
|
drawable_width = wined3d_texture_get_level_pow2_width(depth_stencil, ds_level);
|
||||||
|
drawable_height = wined3d_texture_get_level_pow2_height(depth_stencil, ds_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth_stencil)
|
||||||
|
{
|
||||||
|
DWORD ds_location = render_offscreen ? dsv->resource->draw_binding : WINED3D_LOCATION_DRAWABLE;
|
||||||
|
struct wined3d_texture *ds = wined3d_texture_from_resource(dsv->resource);
|
||||||
|
|
||||||
|
if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL)
|
||||||
|
&& !is_full_clear(ds, dsv->sub_resource_idx, draw_rect, rect_count ? clear_rect : NULL))
|
||||||
|
wined3d_texture_load_location(ds, dsv->sub_resource_idx, context, ds_location);
|
||||||
|
else
|
||||||
|
wined3d_texture_prepare_location(ds, dsv->sub_resource_idx, context, ds_location);
|
||||||
|
|
||||||
|
if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
|
||||||
|
{
|
||||||
|
wined3d_texture_validate_location(ds, dsv->sub_resource_idx, ds_location);
|
||||||
|
wined3d_texture_invalidate_location(ds, dsv->sub_resource_idx, ~ds_location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wined3d_context_gl_apply_clear_state(context_gl, state, rt_count, fb))
|
||||||
|
{
|
||||||
|
context_release(context);
|
||||||
|
WARN("Failed to apply clear state, skipping clear.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only set the values up once, as they are not changing. */
|
||||||
|
if (flags & WINED3DCLEAR_STENCIL)
|
||||||
|
{
|
||||||
|
if (gl_info->supported[EXT_STENCIL_TWO_SIDE])
|
||||||
|
{
|
||||||
|
gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
|
||||||
|
context_invalidate_state(context, STATE_RENDER(WINED3D_RS_TWOSIDEDSTENCILMODE));
|
||||||
|
}
|
||||||
|
gl_info->gl_ops.gl.p_glStencilMask(~0u);
|
||||||
|
context_invalidate_state(context, STATE_RENDER(WINED3D_RS_STENCILWRITEMASK));
|
||||||
|
gl_info->gl_ops.gl.p_glClearStencil(stencil);
|
||||||
|
checkGLcall("glClearStencil");
|
||||||
|
clear_mask = clear_mask | GL_STENCIL_BUFFER_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & WINED3DCLEAR_ZBUFFER)
|
||||||
|
{
|
||||||
|
gl_info->gl_ops.gl.p_glDepthMask(GL_TRUE);
|
||||||
|
context_invalidate_state(context, STATE_RENDER(WINED3D_RS_ZWRITEENABLE));
|
||||||
|
gl_info->gl_ops.gl.p_glClearDepth(depth);
|
||||||
|
checkGLcall("glClearDepth");
|
||||||
|
clear_mask = clear_mask | GL_DEPTH_BUFFER_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & WINED3DCLEAR_TARGET)
|
||||||
|
{
|
||||||
|
for (i = 0; i < rt_count; ++i)
|
||||||
|
{
|
||||||
|
struct wined3d_rendertarget_view *rtv = fb->render_targets[i];
|
||||||
|
struct wined3d_texture *texture;
|
||||||
|
|
||||||
|
if (!rtv)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (rtv->resource->type == WINED3D_RTYPE_BUFFER)
|
||||||
|
{
|
||||||
|
FIXME("Not supported on buffer resources.\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture = texture_from_resource(rtv->resource);
|
||||||
|
wined3d_texture_validate_location(texture, rtv->sub_resource_idx, rtv->resource->draw_binding);
|
||||||
|
wined3d_texture_invalidate_location(texture, rtv->sub_resource_idx, ~rtv->resource->draw_binding);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB] && needs_srgb_write(context->d3d_info, state, fb))
|
||||||
|
{
|
||||||
|
if (rt_count > 1)
|
||||||
|
WARN("Clearing multiple sRGB render targets without GL_ARB_framebuffer_sRGB "
|
||||||
|
"support, this might cause graphical issues.\n");
|
||||||
|
|
||||||
|
wined3d_colour_srgb_from_linear(&colour_srgb, colour);
|
||||||
|
colour = &colour_srgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||||
|
context_invalidate_state(context, STATE_BLEND);
|
||||||
|
gl_info->gl_ops.gl.p_glClearColor(colour->r, colour->g, colour->b, colour->a);
|
||||||
|
checkGLcall("glClearColor");
|
||||||
|
clear_mask = clear_mask | GL_COLOR_BUFFER_BIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rect_count)
|
||||||
|
{
|
||||||
|
if (render_offscreen)
|
||||||
|
{
|
||||||
|
gl_info->gl_ops.gl.p_glScissor(draw_rect->left, draw_rect->top,
|
||||||
|
draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gl_info->gl_ops.gl.p_glScissor(draw_rect->left, drawable_height - draw_rect->bottom,
|
||||||
|
draw_rect->right - draw_rect->left, draw_rect->bottom - draw_rect->top);
|
||||||
|
}
|
||||||
|
gl_info->gl_ops.gl.p_glClear(clear_mask);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RECT current_rect;
|
||||||
|
|
||||||
|
/* Now process each rect in turn. */
|
||||||
|
for (i = 0; i < rect_count; ++i)
|
||||||
|
{
|
||||||
|
/* Note that GL uses lower left, width/height. */
|
||||||
|
IntersectRect(¤t_rect, draw_rect, &clear_rect[i]);
|
||||||
|
|
||||||
|
TRACE("clear_rect[%u] %s, current_rect %s.\n", i,
|
||||||
|
wine_dbgstr_rect(&clear_rect[i]),
|
||||||
|
wine_dbgstr_rect(¤t_rect));
|
||||||
|
|
||||||
|
/* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored
|
||||||
|
* silently. The rectangle is not cleared, no error is returned,
|
||||||
|
* but further rectangles are still cleared if they are valid. */
|
||||||
|
if (current_rect.left > current_rect.right || current_rect.top > current_rect.bottom)
|
||||||
|
{
|
||||||
|
TRACE("Rectangle with negative dimensions, ignoring.\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (render_offscreen)
|
||||||
|
{
|
||||||
|
gl_info->gl_ops.gl.p_glScissor(current_rect.left, current_rect.top,
|
||||||
|
current_rect.right - current_rect.left, current_rect.bottom - current_rect.top);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gl_info->gl_ops.gl.p_glScissor(current_rect.left, drawable_height - current_rect.bottom,
|
||||||
|
current_rect.right - current_rect.left, current_rect.bottom - current_rect.top);
|
||||||
|
}
|
||||||
|
gl_info->gl_ops.gl.p_glClear(clear_mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context->scissor_rect_count = WINED3D_MAX_VIEWPORTS;
|
||||||
|
checkGLcall("clear");
|
||||||
|
|
||||||
|
if (flags & WINED3DCLEAR_TARGET && target->swapchain && target->swapchain->front_buffer == target)
|
||||||
|
gl_info->gl_ops.gl.p_glFlush();
|
||||||
|
|
||||||
|
context_release(context);
|
||||||
|
}
|
||||||
|
|
||||||
static bool ffp_blitter_use_cpu_clear(struct wined3d_rendertarget_view *view)
|
static bool ffp_blitter_use_cpu_clear(struct wined3d_rendertarget_view *view)
|
||||||
{
|
{
|
||||||
struct wined3d_resource *resource;
|
struct wined3d_resource *resource;
|
||||||
|
@ -5262,7 +5510,7 @@ static void ffp_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de
|
||||||
|
|
||||||
if (have_identical_size)
|
if (have_identical_size)
|
||||||
{
|
{
|
||||||
device_clear_render_targets(device, rt_count, fb, rect_count,
|
ffp_blitter_clear_rendertargets(device, rt_count, fb, rect_count,
|
||||||
clear_rects, draw_rect, flags, colour, depth, stencil);
|
clear_rects, draw_rect, flags, colour, depth, stencil);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -5274,14 +5522,14 @@ static void ffp_blitter_clear(struct wined3d_blitter *blitter, struct wined3d_de
|
||||||
|
|
||||||
tmp_fb.render_targets[0] = view;
|
tmp_fb.render_targets[0] = view;
|
||||||
tmp_fb.depth_stencil = NULL;
|
tmp_fb.depth_stencil = NULL;
|
||||||
device_clear_render_targets(device, 1, &tmp_fb, rect_count,
|
ffp_blitter_clear_rendertargets(device, 1, &tmp_fb, rect_count,
|
||||||
clear_rects, draw_rect, WINED3DCLEAR_TARGET, colour, depth, stencil);
|
clear_rects, draw_rect, WINED3DCLEAR_TARGET, colour, depth, stencil);
|
||||||
}
|
}
|
||||||
if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
|
if (flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL))
|
||||||
{
|
{
|
||||||
tmp_fb.render_targets[0] = NULL;
|
tmp_fb.render_targets[0] = NULL;
|
||||||
tmp_fb.depth_stencil = fb->depth_stencil;
|
tmp_fb.depth_stencil = fb->depth_stencil;
|
||||||
device_clear_render_targets(device, 0, &tmp_fb, rect_count,
|
ffp_blitter_clear_rendertargets(device, 0, &tmp_fb, rect_count,
|
||||||
clear_rects, draw_rect, flags & ~WINED3DCLEAR_TARGET, colour, depth, stencil);
|
clear_rects, draw_rect, flags & ~WINED3DCLEAR_TARGET, colour, depth, stencil);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3431,9 +3431,6 @@ struct wined3d_device
|
||||||
};
|
};
|
||||||
|
|
||||||
void wined3d_device_cleanup(struct wined3d_device *device) DECLSPEC_HIDDEN;
|
void wined3d_device_cleanup(struct wined3d_device *device) DECLSPEC_HIDDEN;
|
||||||
void device_clear_render_targets(struct wined3d_device *device, UINT rt_count, const struct wined3d_fb_state *fb,
|
|
||||||
UINT rect_count, const RECT *rects, const RECT *draw_rect, DWORD flags,
|
|
||||||
const struct wined3d_color *color, float depth, DWORD stencil) DECLSPEC_HIDDEN;
|
|
||||||
BOOL device_context_add(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN;
|
BOOL device_context_add(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN;
|
||||||
void device_context_remove(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN;
|
void device_context_remove(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN;
|
||||||
void wined3d_device_create_default_samplers(struct wined3d_device *device,
|
void wined3d_device_create_default_samplers(struct wined3d_device *device,
|
||||||
|
|
Loading…
Reference in New Issue