|
|
@ -3624,43 +3624,45 @@ static void copy_transfer_data(struct pipe_resource *res, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static bool check_transfer_bounds(struct vrend_resource *res, |
|
|
|
static bool check_transfer_bounds(struct vrend_resource *res, |
|
|
|
uint32_t level, struct pipe_box *box) |
|
|
|
const struct vrend_transfer_info *info) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int lwidth, lheight; |
|
|
|
int lwidth, lheight; |
|
|
|
|
|
|
|
|
|
|
|
/* check mipmap level is in bounds */ |
|
|
|
/* check mipmap level is in bounds */ |
|
|
|
if (level > res->base.last_level) |
|
|
|
if (info->level > res->base.last_level) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
/* these will catch bad y/z/w/d with 1D textures etc */ |
|
|
|
/* these will catch bad y/z/w/d with 1D textures etc */ |
|
|
|
lwidth = u_minify(res->base.width0, level); |
|
|
|
lwidth = u_minify(res->base.width0, info->level); |
|
|
|
if (box->width > lwidth) |
|
|
|
if (info->box->width > lwidth) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (box->x > lwidth) |
|
|
|
if (info->box->x > lwidth) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (box->width + box->x > lwidth) |
|
|
|
if (info->box->width + info->box->x > lwidth) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
lheight = u_minify(res->base.height0, level); |
|
|
|
lheight = u_minify(res->base.height0, info->level); |
|
|
|
if (box->height > lheight) |
|
|
|
if (info->box->height > lheight) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (box->y > lheight) |
|
|
|
if (info->box->y > lheight) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (box->height + box->y > lheight) |
|
|
|
if (info->box->height + info->box->y > lheight) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
if (res->base.target == PIPE_TEXTURE_3D) { |
|
|
|
if (res->base.target == PIPE_TEXTURE_3D) { |
|
|
|
int ldepth = u_minify(res->base.depth0, level); |
|
|
|
int ldepth = u_minify(res->base.depth0, info->level); |
|
|
|
if (box->depth > ldepth) |
|
|
|
if (info->box->depth > ldepth) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (box->z > ldepth) |
|
|
|
if (info->box->z > ldepth) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (box->z + box->depth > ldepth) |
|
|
|
if (info->box->z + info->box->depth > ldepth) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
if (box->depth > res->base.array_size) |
|
|
|
if (info->box->depth > res->base.array_size) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (box->z > res->base.array_size) |
|
|
|
if (info->box->z > res->base.array_size) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (box->z + box->depth > res->base.array_size) |
|
|
|
if (info->box->z + info->box->depth > res->base.array_size) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -3672,27 +3674,49 @@ static bool check_iov_bounds(struct vrend_resource *res, |
|
|
|
struct iovec *iov, int num_iovs) |
|
|
|
struct iovec *iov, int num_iovs) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int elsize = util_format_get_blocksize(res->base.format); |
|
|
|
int elsize = util_format_get_blocksize(res->base.format); |
|
|
|
GLuint send_size = util_format_get_nblocks(res->base.format, info->box->width, |
|
|
|
GLuint send_size; |
|
|
|
info->box->height) * elsize * info->box->depth; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GLuint iovsize = vrend_get_iovec_size(iov, num_iovs); |
|
|
|
GLuint iovsize = vrend_get_iovec_size(iov, num_iovs); |
|
|
|
|
|
|
|
GLuint valid_stride, valid_layer_stride; |
|
|
|
if (iovsize < info->offset) |
|
|
|
|
|
|
|
return false; |
|
|
|
/* validate the send size */ |
|
|
|
if (iovsize < send_size) |
|
|
|
valid_stride = info->box->width * elsize; |
|
|
|
return false; |
|
|
|
if (info->stride) { |
|
|
|
if (iovsize < info->offset + send_size) |
|
|
|
/* only validate passed in stride for boxes with height */ |
|
|
|
|
|
|
|
if (info->box->height > 1) { |
|
|
|
|
|
|
|
if (info->stride < valid_stride) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
valid_stride = info->stride; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
valid_layer_stride = util_format_get_nblocks(res->base.format, valid_stride / elsize, |
|
|
|
|
|
|
|
info->box->height) * elsize; |
|
|
|
|
|
|
|
|
|
|
|
/* layer stride only makes sense for 3d,cube and arrays */ |
|
|
|
/* layer stride only makes sense for 3d,cube and arrays */ |
|
|
|
if (info->layer_stride && |
|
|
|
if (info->layer_stride) { |
|
|
|
(res->base.target != PIPE_TEXTURE_3D && |
|
|
|
if ((res->base.target != PIPE_TEXTURE_3D && |
|
|
|
res->base.target != PIPE_TEXTURE_CUBE && |
|
|
|
res->base.target != PIPE_TEXTURE_CUBE && |
|
|
|
res->base.target != PIPE_TEXTURE_1D_ARRAY && |
|
|
|
res->base.target != PIPE_TEXTURE_1D_ARRAY && |
|
|
|
res->base.target != PIPE_TEXTURE_2D_ARRAY && |
|
|
|
res->base.target != PIPE_TEXTURE_2D_ARRAY && |
|
|
|
res->base.target != PIPE_TEXTURE_CUBE_ARRAY)) |
|
|
|
res->base.target != PIPE_TEXTURE_CUBE_ARRAY)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* only validate passed in layer_stride for boxes with depth */ |
|
|
|
|
|
|
|
if (info->box->depth > 1) { |
|
|
|
|
|
|
|
if (info->layer_stride < valid_layer_stride) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
valid_layer_stride = info->layer_stride; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
send_size = valid_layer_stride * info->box->depth; |
|
|
|
|
|
|
|
if (iovsize < info->offset) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
if (iovsize < send_size) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
if (iovsize < info->offset + send_size) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -4179,7 +4203,7 @@ int vrend_renderer_transfer_iov(const struct vrend_transfer_info *info, |
|
|
|
return EINVAL; |
|
|
|
return EINVAL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!check_transfer_bounds(res, info->level, info->box)) |
|
|
|
if (!check_transfer_bounds(res, info)) |
|
|
|
return EINVAL; |
|
|
|
return EINVAL; |
|
|
|
|
|
|
|
|
|
|
|
if (!check_iov_bounds(res, info, iov, num_iovs)) |
|
|
|
if (!check_iov_bounds(res, info, iov, num_iovs)) |
|
|
@ -4207,7 +4231,7 @@ int vrend_transfer_inline_write(struct vrend_context *ctx, |
|
|
|
return EINVAL; |
|
|
|
return EINVAL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!check_transfer_bounds(res, info->level, info->box)) { |
|
|
|
if (!check_transfer_bounds(res, info)) { |
|
|
|
report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, info->handle); |
|
|
|
report_context_error(ctx, VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, info->handle); |
|
|
|
return EINVAL; |
|
|
|
return EINVAL; |
|
|
|
} |
|
|
|
} |
|
|
|