diff --git a/src/gallium/frontends/va/image.c b/src/gallium/frontends/va/image.c index fbe9df38297..b74ce8fe319 100644 --- a/src/gallium/frontends/va/image.c +++ b/src/gallium/frontends/va/image.c @@ -468,7 +468,7 @@ vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y, unsigned int width, unsigned int height, VAImageID image) { vlVaDriver *drv; - vlVaSurface *surf; + vlVaSurface *surf, tmp_surf = {0}; vlVaBuffer *img_buf; VAImage *vaimage; struct pipe_resource *view_resources[VL_NUM_COMPONENTS]; @@ -519,9 +519,43 @@ vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y, } format = VaFourccToPipeFormat(vaimage->format.fourcc); - if (format != surf->buffer->buffer_format) { + if (format == PIPE_FORMAT_NONE) { mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; + return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; + } + + if (format != surf->buffer->buffer_format) { + tmp_surf.templat.buffer_format = format; + tmp_surf.templat.width = vaimage->width; + tmp_surf.templat.height = vaimage->height; + VAStatus ret = + vlVaHandleSurfaceAllocate(drv, &tmp_surf, &tmp_surf.templat, NULL, 0); + if (ret != VA_STATUS_SUCCESS) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + VARectangle src_rect = { + .x = x, + .y = y, + .width = width, + .height = height, + }; + VARectangle dst_rect = { + .x = 0, + .y = 0, + .width = vaimage->width, + .height = vaimage->height, + }; + VAProcPipelineParameterBuffer proc = {0}; + ret = vlVaPostProcCompositor(drv, &src_rect, &dst_rect, + surf->buffer, tmp_surf.buffer, + VL_COMPOSITOR_NONE, &proc); + if (ret != VA_STATUS_SUCCESS) { + tmp_surf.buffer->destroy(tmp_surf.buffer); + mtx_unlock(&drv->mutex); + return ret; + } + surf = &tmp_surf; } memset(view_resources, 0, sizeof(view_resources)); @@ -562,11 +596,46 @@ vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y, pipe_texture_unmap(drv->pipe, transfer); } } + if (tmp_surf.buffer) + tmp_surf.buffer->destroy(tmp_surf.buffer); mtx_unlock(&drv->mutex); return VA_STATUS_SUCCESS; } +static void +vlVaUploadImage(vlVaDriver *drv, vlVaSurface *surf, vlVaBuffer *buf, VAImage *image) +{ + uint8_t *data[3]; + unsigned pitches[3]; + struct pipe_resource *view_resources[VL_NUM_COMPONENTS] = {0}; + + surf->buffer->get_resources(surf->buffer, view_resources); + + for (unsigned i = 0; i < MIN2(image->num_planes, 3); i++) { + data[i] = ((uint8_t*)buf->data) + image->offsets[i]; + pitches[i] = image->pitches[i]; + } + + for (unsigned i = 0; i < image->num_planes; ++i) { + unsigned width, height; + struct pipe_resource *tex; + + if (!view_resources[i]) continue; + tex = view_resources[i]; + + vlVaVideoSurfaceSize(surf, i, &width, &height); + for (unsigned j = 0; j < tex->array_size; ++j) { + struct pipe_box dst_box; + u_box_3d(0, 0, j, width, height, 1, &dst_box); + drv->pipe->texture_subdata(drv->pipe, tex, 0, + PIPE_MAP_WRITE, &dst_box, + data[i] + pitches[i] * j, + pitches[i] * view_resources[i]->array_size, 0); + } + } +} + VAStatus vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image, int src_x, int src_y, unsigned int src_width, unsigned int src_height, @@ -576,10 +645,7 @@ vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image, vlVaSurface *surf; vlVaBuffer *img_buf; VAImage *vaimage; - struct pipe_resource *view_resources[VL_NUM_COMPONENTS]; enum pipe_format format; - uint8_t *data[3]; - unsigned pitches[3], i, j; if (!ctx) return VA_STATUS_ERROR_INVALID_CONTEXT; @@ -613,36 +679,51 @@ vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image, } format = VaFourccToPipeFormat(vaimage->format.fourcc); - if (format != surf->buffer->buffer_format) { + if (format == PIPE_FORMAT_NONE) { mtx_unlock(&drv->mutex); - return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; + return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; } - memset(view_resources, 0, sizeof(view_resources)); - surf->buffer->get_resources(surf->buffer, view_resources); - - for (i = 0; i < MIN2(vaimage->num_planes, 3); i++) { - data[i] = ((uint8_t*)img_buf->data) + vaimage->offsets[i]; - pitches[i] = vaimage->pitches[i]; - } - - for (i = 0; i < vaimage->num_planes; ++i) { - unsigned width, height; - struct pipe_resource *tex; - - if (!view_resources[i]) continue; - tex = view_resources[i]; - - vlVaVideoSurfaceSize(surf, i, &width, &height); - for (j = 0; j < tex->array_size; ++j) { - struct pipe_box dst_box; - u_box_3d(0, 0, j, width, height, 1, &dst_box); - drv->pipe->texture_subdata(drv->pipe, tex, 0, - PIPE_MAP_WRITE, &dst_box, - data[i] + pitches[i] * j, - pitches[i] * view_resources[i]->array_size, 0); + if (format != surf->buffer->buffer_format || + dest_width != src_width || dest_height != src_height || + src_x != 0 || dest_x != 0 || src_y != 0 || dest_y != 0) { + struct vlVaSurface tmp_surf = { + .templat = { + .buffer_format = format, + .width = vaimage->width, + .height = vaimage->height, + }, + }; + VAStatus ret = + vlVaHandleSurfaceAllocate(drv, &tmp_surf, &tmp_surf.templat, NULL, 0); + if (ret != VA_STATUS_SUCCESS) { + mtx_unlock(&drv->mutex); + return VA_STATUS_ERROR_ALLOCATION_FAILED; } + vlVaUploadImage(drv, &tmp_surf, img_buf, vaimage); + VARectangle src_rect = { + .x = src_x, + .y = src_y, + .width = src_width, + .height = src_height, + }; + VARectangle dst_rect = { + .x = dest_x, + .y = dest_y, + .width = dest_width, + .height = dest_height, + }; + VAProcPipelineParameterBuffer proc = {0}; + ret = vlVaPostProcCompositor(drv, &src_rect, &dst_rect, + tmp_surf.buffer, surf->buffer, + VL_COMPOSITOR_NONE, &proc); + tmp_surf.buffer->destroy(tmp_surf.buffer); + mtx_unlock(&drv->mutex); + return ret; } + + vlVaUploadImage(drv, surf, img_buf, vaimage); + drv->pipe->flush(drv->pipe, NULL, 0); mtx_unlock(&drv->mutex);