diff options
Diffstat (limited to 'i965_drv_video/i965_drv_video.c')
-rw-r--r-- | i965_drv_video/i965_drv_video.c | 283 |
1 files changed, 259 insertions, 24 deletions
diff --git a/i965_drv_video/i965_drv_video.c b/i965_drv_video/i965_drv_video.c index ace2181..104c105 100644 --- a/i965_drv_video/i965_drv_video.c +++ b/i965_drv_video/i965_drv_video.c @@ -54,6 +54,22 @@ enum { I965_SURFACETYPE_INDEXED }; +/* List of supported image formats */ +typedef struct { + unsigned int type; + VAImageFormat va_format; +} i965_image_format_map_t; + +static const i965_image_format_map_t +i965_image_formats_map[I965_MAX_IMAGE_FORMATS + 1] = { + { I965_SURFACETYPE_YUV, + { VA_FOURCC('Y','V','1','2'), VA_LSB_FIRST, 12, } }, + { I965_SURFACETYPE_YUV, + { VA_FOURCC('I','4','2','0'), VA_LSB_FIRST, 12, } }, + { I965_SURFACETYPE_YUV, + { VA_FOURCC('N','V','1','2'), VA_LSB_FIRST, 12, } }, +}; + /* List of supported subpicture formats */ typedef struct { unsigned int type; @@ -70,13 +86,21 @@ i965_subpic_formats_map[I965_MAX_SUBPIC_FORMATS + 1] = { { I965_SURFACETYPE_INDEXED, I965_SURFACEFORMAT_A4P4_UNORM, { VA_FOURCC('A','I','4','4'), VA_MSB_FIRST, 8, }, 0 }, + { I965_SURFACETYPE_RGBA, I965_SURFACEFORMAT_B8G8R8A8_UNORM, + { VA_FOURCC('B','G','R','A'), VA_LSB_FIRST, 32, + 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, + 0 }, + { I965_SURFACETYPE_RGBA, I965_SURFACEFORMAT_R8G8B8A8_UNORM, + { VA_FOURCC('R','G','B','A'), VA_LSB_FIRST, 32, + 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, + 0 }, }; static const i965_subpic_format_map_t * get_subpic_format(const VAImageFormat *va_format) { unsigned int i; - for (i = 0; i < sizeof(i965_subpic_formats_map)/sizeof(i965_subpic_formats_map[0]); i++) { + for (i = 0; i965_subpic_formats_map[i].type != 0; i++) { const i965_subpic_format_map_t * const m = &i965_subpic_formats_map[i]; if (m->va_format.fourcc == va_format->fourcc && (m->type == I965_SURFACETYPE_RGBA ? @@ -364,8 +388,10 @@ i965_CreateSurfaces(VADriverContextP ctx, surfaces[i] = surfaceID; obj_surface->status = VASurfaceReady; obj_surface->subpic = VA_INVALID_ID; - obj_surface->width = ALIGN(width, 16); - obj_surface->height = ALIGN(height, 16); + obj_surface->orig_width = width; + obj_surface->orig_height = height; + obj_surface->width = ALIGN(obj_surface->orig_width, 16); + obj_surface->height = ALIGN(obj_surface->orig_height, 16); obj_surface->size = SIZE_YUV420(obj_surface->width, obj_surface->height); obj_surface->flags = SURFACE_REFERENCED; obj_surface->bo = NULL; @@ -411,8 +437,16 @@ i965_QueryImageFormats(VADriverContextP ctx, VAImageFormat *format_list, /* out */ int *num_formats) /* out */ { + int n; + + for (n = 0; i965_image_formats_map[n].va_format.fourcc != 0; n++) { + const i965_image_format_map_t * const m = &i965_image_formats_map[n]; + if (format_list) + format_list[n] = m->va_format; + } + if (num_formats) - *num_formats = 0; + *num_formats = n; return VA_STATUS_SUCCESS; } @@ -488,6 +522,7 @@ i965_CreateSubpicture(VADriverContextP ctx, obj_subpic->format = m->format; obj_subpic->width = obj_image->image.width; obj_subpic->height = obj_image->image.height; + obj_subpic->pitch = obj_image->image.pitches[0]; obj_subpic->bo = obj_image->bo; return VA_STATUS_SUCCESS; } @@ -508,7 +543,8 @@ i965_SetSubpictureImage(VADriverContextP ctx, VASubpictureID subpicture, VAImageID image) { - return VA_STATUS_SUCCESS; + /* TODO */ + return VA_STATUS_ERROR_UNIMPLEMENTED; } VAStatus @@ -518,7 +554,8 @@ i965_SetSubpictureChromakey(VADriverContextP ctx, unsigned int chromakey_max, unsigned int chromakey_mask) { - return VA_STATUS_SUCCESS; + /* TODO */ + return VA_STATUS_ERROR_UNIMPLEMENTED; } VAStatus @@ -526,7 +563,8 @@ i965_SetSubpictureGlobalAlpha(VADriverContextP ctx, VASubpictureID subpicture, float global_alpha) { - return VA_STATUS_SUCCESS; + /* TODO */ + return VA_STATUS_ERROR_UNIMPLEMENTED; } VAStatus @@ -661,6 +699,7 @@ i965_CreateContext(VADriverContextP ctx, VAContextID *context) /* out */ { struct i965_driver_data *i965 = i965_driver_data(ctx); + struct i965_render_state *render_state = &i965->render_state; struct object_config *obj_config = CONFIG(config_id); struct object_context *obj_context = NULL; VAStatus vaStatus = VA_STATUS_SUCCESS; @@ -682,6 +721,16 @@ i965_CreateContext(VADriverContextP ctx, return vaStatus; } + switch (obj_config->profile) { + case VAProfileH264Baseline: + case VAProfileH264Main: + case VAProfileH264High: + render_state->interleaved_uv = 1; + break; + default: + render_state->interleaved_uv = 0; + } + obj_context->context_id = contextID; *context = contextID; memset(&obj_context->decode_state, 0, sizeof(obj_context->decode_state)); @@ -1076,7 +1125,6 @@ VAStatus i965_EndPicture(VADriverContextP ctx, VAContextID context) { struct i965_driver_data *i965 = i965_driver_data(ctx); - struct i965_render_state *render_state = &i965->render_state; struct object_context *obj_context = CONTEXT(context); struct object_config *obj_config; VAContextID config; @@ -1092,17 +1140,6 @@ i965_EndPicture(VADriverContextP ctx, VAContextID context) obj_config = CONFIG(config); assert(obj_config); - switch (obj_config->profile) { - case VAProfileH264Baseline: - case VAProfileH264Main: - case VAProfileH264High: - render_state->interleaved_uv = 1; - break; - - default: - render_state->interleaved_uv = 0; - } - i965_media_decode_picture(ctx, obj_config->profile, &obj_context->decode_state); obj_context->decode_state.current_render_target = -1; obj_context->decode_state.num_slice_params = 0; @@ -1175,7 +1212,7 @@ i965_GetDisplayAttributes(VADriverContextP ctx, int num_attributes) { /* TODO */ - return VA_STATUS_ERROR_UNKNOWN; + return VA_STATUS_ERROR_UNIMPLEMENTED; } /* @@ -1190,7 +1227,7 @@ i965_SetDisplayAttributes(VADriverContextP ctx, int num_attributes) { /* TODO */ - return VA_STATUS_ERROR_UNKNOWN; + return VA_STATUS_ERROR_UNIMPLEMENTED; } VAStatus @@ -1200,7 +1237,7 @@ i965_DbgCopySurfaceToBuffer(VADriverContextP ctx, unsigned int *stride) /* out */ { /* TODO */ - return VA_STATUS_ERROR_UNKNOWN; + return VA_STATUS_ERROR_UNIMPLEMENTED; } static VAStatus @@ -1299,6 +1336,43 @@ i965_CreateImage(VADriverContextP ctx, image->component_order[1] = 'G'; image->component_order[2] = 'B'; break; + case VA_FOURCC('A','R','G','B'): + case VA_FOURCC('A','B','G','R'): + case VA_FOURCC('B','G','R','A'): + case VA_FOURCC('R','G','B','A'): + image->num_planes = 1; + image->pitches[0] = width * 4; + image->offsets[0] = 0; + image->data_size = image->offsets[0] + image->pitches[0] * height; + break; + case VA_FOURCC('Y','V','1','2'): + image->num_planes = 3; + image->pitches[0] = width; + image->offsets[0] = 0; + image->pitches[1] = width2; + image->offsets[1] = size + size2; + image->pitches[2] = width2; + image->offsets[2] = size; + image->data_size = size + 2 * size2; + break; + case VA_FOURCC('I','4','2','0'): + image->num_planes = 3; + image->pitches[0] = width; + image->offsets[0] = 0; + image->pitches[1] = width2; + image->offsets[1] = size; + image->pitches[2] = width2; + image->offsets[2] = size + size2; + image->data_size = size + 2 * size2; + break; + case VA_FOURCC('N','V','1','2'): + image->num_planes = 2; + image->pitches[0] = width; + image->offsets[0] = 0; + image->pitches[1] = width; + image->offsets[1] = size; + image->data_size = size + 2 * size2; + break; default: goto error; } @@ -1333,7 +1407,8 @@ VAStatus i965_DeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image) /* out */ { - return VA_STATUS_SUCCESS; + /* TODO */ + return VA_STATUS_ERROR_OPERATION_FAILED; } static void @@ -1394,6 +1469,109 @@ i965_SetImagePalette(VADriverContextP ctx, return VA_STATUS_SUCCESS; } +static inline void +memcpy_pic(uint8_t *dst, unsigned int dst_stride, + const uint8_t *src, unsigned int src_stride, + unsigned int len, unsigned int height) +{ + unsigned int i; + + for (i = 0; i < height; i++) { + memcpy(dst, src, len); + dst += dst_stride; + src += src_stride; + } +} + +static void +get_image_i420(struct object_image *obj_image, uint8_t *image_data, + struct object_surface *obj_surface, + const VARectangle *rect) +{ + uint8_t *dst[3], *src[3]; + const int Y = 0; + const int U = obj_image->image.format.fourcc == VA_FOURCC_YV12 ? 2 : 1; + const int V = obj_image->image.format.fourcc == VA_FOURCC_YV12 ? 1 : 2; + + if (!obj_surface->bo) + return; + + dri_bo_map(obj_surface->bo, 0); + + if (!obj_surface->bo->virtual) + return; + + /* Dest VA image has either I420 or YV12 format. + Source VA surface alway has I420 format */ + dst[Y] = image_data + obj_image->image.offsets[Y]; + src[0] = (uint8_t *)obj_surface->bo->virtual; + dst[U] = image_data + obj_image->image.offsets[U]; + src[1] = src[0] + obj_surface->width * obj_surface->height; + dst[V] = image_data + obj_image->image.offsets[V]; + src[2] = src[1] + (obj_surface->width / 2) * (obj_surface->height / 2); + + /* Y plane */ + dst[Y] += rect->y * obj_image->image.pitches[Y] + rect->x; + src[0] += rect->y * obj_surface->width + rect->x; + memcpy_pic(dst[Y], obj_image->image.pitches[Y], + src[0], obj_surface->width, + rect->width, rect->height); + + /* U plane */ + dst[U] += (rect->y / 2) * obj_image->image.pitches[U] + rect->x / 2; + src[1] += (rect->y / 2) * obj_surface->width / 2 + rect->x / 2; + memcpy_pic(dst[U], obj_image->image.pitches[U], + src[1], obj_surface->width / 2, + rect->width / 2, rect->height / 2); + + /* V plane */ + dst[V] += (rect->y / 2) * obj_image->image.pitches[V] + rect->x / 2; + src[2] += (rect->y / 2) * obj_surface->width / 2 + rect->x / 2; + memcpy_pic(dst[V], obj_image->image.pitches[V], + src[2], obj_surface->width / 2, + rect->width / 2, rect->height / 2); + + dri_bo_unmap(obj_surface->bo); +} + +static void +get_image_nv12(struct object_image *obj_image, uint8_t *image_data, + struct object_surface *obj_surface, + const VARectangle *rect) +{ + uint8_t *dst[2], *src[2]; + + if (!obj_surface->bo) + return; + + dri_bo_map(obj_surface->bo, 0); + + if (!obj_surface->bo->virtual) + return; + + /* Both dest VA image and source surface have NV12 format */ + dst[0] = image_data + obj_image->image.offsets[0]; + src[0] = (uint8_t *)obj_surface->bo->virtual; + dst[1] = image_data + obj_image->image.offsets[1]; + src[1] = src[0] + obj_surface->width * obj_surface->height; + + /* Y plane */ + dst[0] += rect->y * obj_image->image.pitches[0] + rect->x; + src[0] += rect->y * obj_surface->width + rect->x; + memcpy_pic(dst[0], obj_image->image.pitches[0], + src[0], obj_surface->width, + rect->width, rect->height); + + /* UV plane */ + dst[1] += (rect->y / 2) * obj_image->image.pitches[1] + (rect->x & -2); + src[1] += (rect->y / 2) * obj_surface->width + (rect->x & -2); + memcpy_pic(dst[1], obj_image->image.pitches[1], + src[1], obj_surface->width, + rect->width, rect->height / 2); + + dri_bo_unmap(obj_surface->bo); +} + VAStatus i965_GetImage(VADriverContextP ctx, VASurfaceID surface, @@ -1403,7 +1581,64 @@ i965_GetImage(VADriverContextP ctx, unsigned int height, VAImageID image) { - return VA_STATUS_SUCCESS; + struct i965_driver_data *i965 = i965_driver_data(ctx); + struct i965_render_state *render_state = &i965->render_state; + + struct object_surface *obj_surface = SURFACE(surface); + if (!obj_surface) + return VA_STATUS_ERROR_INVALID_SURFACE; + + struct object_image *obj_image = IMAGE(image); + if (!obj_image) + return VA_STATUS_ERROR_INVALID_IMAGE; + + if (x < 0 || y < 0) + return VA_STATUS_ERROR_INVALID_PARAMETER; + if (x + width > obj_surface->orig_width || + y + height > obj_surface->orig_height) + return VA_STATUS_ERROR_INVALID_PARAMETER; + if (x + width > obj_image->image.width || + y + height > obj_image->image.height) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + /* Commit pending operations to the HW */ + intel_batchbuffer_flush(ctx); + + VAStatus va_status; + void *image_data = NULL; + + va_status = i965_MapBuffer(ctx, obj_image->image.buf, &image_data); + if (va_status != VA_STATUS_SUCCESS) + return va_status; + + VARectangle rect; + rect.x = x; + rect.y = y; + rect.width = width; + rect.height = height; + + switch (obj_image->image.format.fourcc) { + case VA_FOURCC('Y','V','1','2'): + case VA_FOURCC('I','4','2','0'): + /* I420 is native format for MPEG-2 decoded surfaces */ + if (render_state->interleaved_uv) + goto operation_failed; + get_image_i420(obj_image, image_data, obj_surface, &rect); + break; + case VA_FOURCC('N','V','1','2'): + /* NV12 is native format for H.264 decoded surfaces */ + if (!render_state->interleaved_uv) + goto operation_failed; + get_image_nv12(obj_image, image_data, obj_surface, &rect); + break; + default: + operation_failed: + va_status = VA_STATUS_ERROR_OPERATION_FAILED; + break; + } + + i965_UnmapBuffer(ctx, obj_image->image.buf); + return va_status; } VAStatus |