0,0 → 1,252 |
/* |
* Mesa 3-D graphics library |
* |
* Copyright (C) 2012-2013 LunarG, Inc. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included |
* in all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
* DEALINGS IN THE SOFTWARE. |
* |
* Authors: |
* Chia-I Wu <olv@lunarg.com> |
*/ |
|
#include "util/u_surface.h" |
|
#include "ilo_blitter.h" |
#include "ilo_context.h" |
#include "ilo_blit.h" |
|
static void |
ilo_resource_copy_region(struct pipe_context *pipe, |
struct pipe_resource *dst, |
unsigned dst_level, |
unsigned dstx, unsigned dsty, unsigned dstz, |
struct pipe_resource *src, |
unsigned src_level, |
const struct pipe_box *src_box) |
{ |
struct ilo_context *ilo = ilo_context(pipe); |
|
if (ilo_blitter_blt_copy_resource(ilo->blitter, |
dst, dst_level, dstx, dsty, dstz, |
src, src_level, src_box)) |
return; |
|
if (ilo_blitter_pipe_copy_resource(ilo->blitter, |
dst, dst_level, dstx, dsty, dstz, |
src, src_level, src_box)) |
return; |
|
util_resource_copy_region(&ilo->base, dst, dst_level, |
dstx, dsty, dstz, src, src_level, src_box); |
} |
|
static void |
ilo_clear(struct pipe_context *pipe, |
unsigned buffers, |
const union pipe_color_union *color, |
double depth, |
unsigned stencil) |
{ |
struct ilo_context *ilo = ilo_context(pipe); |
struct ilo_state_vector *vec = &ilo->state_vector; |
|
if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && vec->fb.state.zsbuf) { |
if (ilo_blitter_rectlist_clear_zs(ilo->blitter, vec->fb.state.zsbuf, |
buffers & PIPE_CLEAR_DEPTHSTENCIL, depth, stencil)) |
buffers &= ~PIPE_CLEAR_DEPTHSTENCIL; |
|
if (!buffers) |
return; |
} |
|
ilo_blitter_pipe_clear_fb(ilo->blitter, buffers, color, depth, stencil); |
} |
|
static void |
ilo_clear_render_target(struct pipe_context *pipe, |
struct pipe_surface *dst, |
const union pipe_color_union *color, |
unsigned dstx, unsigned dsty, |
unsigned width, unsigned height) |
{ |
struct ilo_context *ilo = ilo_context(pipe); |
|
if (!width || !height || dstx >= dst->width || dsty >= dst->height) |
return; |
|
if (dstx + width > dst->width) |
width = dst->width - dstx; |
if (dsty + height > dst->height) |
height = dst->height - dsty; |
|
if (ilo_blitter_blt_clear_rt(ilo->blitter, |
dst, color, dstx, dsty, width, height)) |
return; |
|
ilo_blitter_pipe_clear_rt(ilo->blitter, |
dst, color, dstx, dsty, width, height); |
} |
|
static void |
ilo_clear_depth_stencil(struct pipe_context *pipe, |
struct pipe_surface *dst, |
unsigned clear_flags, |
double depth, |
unsigned stencil, |
unsigned dstx, unsigned dsty, |
unsigned width, unsigned height) |
{ |
struct ilo_context *ilo = ilo_context(pipe); |
|
if (!width || !height || dstx >= dst->width || dsty >= dst->height) |
return; |
|
if (dstx + width > dst->width) |
width = dst->width - dstx; |
if (dsty + height > dst->height) |
height = dst->height - dsty; |
|
if (ilo_blitter_blt_clear_zs(ilo->blitter, |
dst, clear_flags, depth, stencil, dstx, dsty, width, height)) |
return; |
|
ilo_blitter_pipe_clear_zs(ilo->blitter, |
dst, clear_flags, depth, stencil, dstx, dsty, width, height); |
} |
|
static void |
ilo_blit(struct pipe_context *pipe, const struct pipe_blit_info *info) |
{ |
struct ilo_context *ilo = ilo_context(pipe); |
|
ilo_blitter_pipe_blit(ilo->blitter, info); |
} |
|
static void |
ilo_flush_resource(struct pipe_context *pipe, struct pipe_resource *res) |
{ |
struct ilo_context *ilo = ilo_context(pipe); |
const unsigned flags = ILO_TEXTURE_CPU_READ | |
ILO_TEXTURE_BLT_READ | |
ILO_TEXTURE_RENDER_READ; |
|
ilo_blit_resolve_resource(ilo, res, flags); |
} |
|
void |
ilo_blit_resolve_slices_for_hiz(struct ilo_context *ilo, |
struct pipe_resource *res, unsigned level, |
unsigned first_slice, unsigned num_slices, |
unsigned resolve_flags) |
{ |
struct ilo_texture *tex = ilo_texture(res); |
const unsigned any_reader = |
ILO_TEXTURE_RENDER_READ | |
ILO_TEXTURE_BLT_READ | |
ILO_TEXTURE_CPU_READ; |
const unsigned other_writers = |
ILO_TEXTURE_BLT_WRITE | |
ILO_TEXTURE_CPU_WRITE; |
unsigned i; |
|
assert(tex->base.target != PIPE_BUFFER && |
ilo_image_can_enable_aux(&tex->image, level)); |
|
if (resolve_flags & ILO_TEXTURE_RENDER_WRITE) { |
/* |
* When ILO_TEXTURE_RENDER_WRITE is set, there can be no reader. We |
* need to perform a HiZ Buffer Resolve in case the resource was |
* previously written by another writer, unless this is a clear. |
* |
* When slices have different clear values, we perform a Depth Buffer |
* Resolve on all slices not sharing the clear value of the first slice. |
* After resolving, those slices do not use 3DSTATE_CLEAR_PARAMS and can |
* be made to have the same clear value as the first slice does. This |
* way, |
* |
* - 3DSTATE_CLEAR_PARAMS can be set to the clear value of any slice |
* - we will not resolve unnecessarily next time this function is |
* called |
* |
* Since slice clear value is the value the slice is cleared to when |
* ILO_TEXTURE_CLEAR is set, the bit needs to be unset. |
*/ |
assert(!(resolve_flags & (other_writers | any_reader))); |
|
if (!(resolve_flags & ILO_TEXTURE_CLEAR)) { |
const uint32_t first_clear_value = ilo_texture_get_slice(tex, |
level, first_slice)->clear_value; |
bool set_clear_value = false; |
|
for (i = 0; i < num_slices; i++) { |
const struct ilo_texture_slice *slice = |
ilo_texture_get_slice(tex, level, first_slice + i); |
|
if (slice->flags & other_writers) { |
ilo_blitter_rectlist_resolve_hiz(ilo->blitter, |
res, level, first_slice + i); |
} else if (slice->clear_value != first_clear_value && |
(slice->flags & ILO_TEXTURE_RENDER_WRITE)) { |
ilo_blitter_rectlist_resolve_z(ilo->blitter, |
res, level, first_slice + i); |
set_clear_value = true; |
} |
} |
|
if (set_clear_value) { |
/* ILO_TEXTURE_CLEAR will be cleared later */ |
ilo_texture_set_slice_clear_value(tex, level, |
first_slice, num_slices, first_clear_value); |
} |
} |
} |
else if ((resolve_flags & any_reader) || |
((resolve_flags & other_writers) && |
!(resolve_flags & ILO_TEXTURE_CLEAR))) { |
/* |
* When there is at least a reader or writer, we need to perform a |
* Depth Buffer Resolve in case the resource was previously written |
* by ILO_TEXTURE_RENDER_WRITE. |
*/ |
for (i = 0; i < num_slices; i++) { |
const struct ilo_texture_slice *slice = |
ilo_texture_get_slice(tex, level, first_slice + i); |
|
if (slice->flags & ILO_TEXTURE_RENDER_WRITE) { |
ilo_blitter_rectlist_resolve_z(ilo->blitter, |
&tex->base, level, first_slice + i); |
} |
} |
} |
} |
|
/** |
* Initialize blit-related functions. |
*/ |
void |
ilo_init_blit_functions(struct ilo_context *ilo) |
{ |
ilo->base.resource_copy_region = ilo_resource_copy_region; |
ilo->base.blit = ilo_blit; |
ilo->base.flush_resource = ilo_flush_resource; |
|
ilo->base.clear = ilo_clear; |
ilo->base.clear_render_target = ilo_clear_render_target; |
ilo->base.clear_depth_stencil = ilo_clear_depth_stencil; |
} |