+ /* Initialize with base surface attributes, except pixel-formats */
+ for (n = 0; attribs_map[n].type != VASurfaceAttribNone; n++) {
+ VASurfaceAttrib * const attrib = &attribs[n];
+ attrib->type = attribs_map[n].type;
+ attrib->flags = VA_SURFACE_ATTRIB_GETTABLE;
+ attrib->value.type = attribs_map[n].value_type;
+ }
+
+ /* Append image formats */
+ for (i = 0; i < num_image_formats; i++) {
+ VASurfaceAttrib * const attrib = &attribs[n];
+ attrib->type = VASurfaceAttribPixelFormat;
+ attrib->flags = VA_SURFACE_ATTRIB_GETTABLE|VA_SURFACE_ATTRIB_SETTABLE;
+ attrib->value.type = VAGenericValueTypeInteger;
+ attrib->value.value.i = image_formats[i].fourcc;
+ if (++n == num_attribs) {
+ va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
+ goto end;
+ }
+ }
+ num_attribs = n;
+
+ va_status = ctx->vtable->vaGetSurfaceAttributes(
+ ctx, config, attribs, num_attribs);
+ if (va_status != VA_STATUS_SUCCESS)
+ goto end;
+
+ /* Remove invalid entries */
+ out_num_attribs = 0;
+ for (n = 0; n < num_attribs; n++) {
+ VASurfaceAttrib * const attrib = &attribs[n];
+
+ if (attrib->flags == VA_SURFACE_ATTRIB_NOT_SUPPORTED)
+ continue;
+
+ // Accept all surface attributes that are not pixel-formats
+ if (attrib->type != VASurfaceAttribPixelFormat) {
+ out_num_attribs++;
+ continue;
+ }
+
+ // Drop invalid pixel-format attribute
+ if (!attrib->value.value.i) {
+ attrib->flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
+ continue;
+ }
+
+ // Check for duplicates
+ int is_duplicate = 0;
+ for (i = n - 1; i >= 0 && !is_duplicate; i--) {
+ const VASurfaceAttrib * const prev_attrib = &attribs[i];
+ if (prev_attrib->type != VASurfaceAttribPixelFormat)
+ break;
+ is_duplicate = prev_attrib->value.value.i == attrib->value.value.i;
+ }
+ if (is_duplicate)
+ attrib->flags = VA_SURFACE_ATTRIB_NOT_SUPPORTED;
+ else
+ out_num_attribs++;
+ }
+
+ if (*out_num_attribs_ptr < out_num_attribs) {
+ *out_num_attribs_ptr = out_num_attribs;
+ va_status = VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
+ goto end;
+ }
+
+ out_attrib = out_attribs;
+ for (n = 0; n < num_attribs; n++) {
+ const VASurfaceAttrib * const attrib = &attribs[n];
+ if (attrib->flags == VA_SURFACE_ATTRIB_NOT_SUPPORTED)
+ continue;
+ *out_attrib++ = *attrib;
+ }
+
+end:
+ free(attribs);
+ free(image_formats);
+ return va_status;
+}
+
+VAStatus
+vaQuerySurfaceAttributes(
+ VADisplay dpy,
+ VAConfigID config,
+ VASurfaceAttrib *attrib_list,
+ unsigned int *num_attribs
+)
+{
+ VADriverContextP ctx;
+ VAStatus vaStatus;
+
+ CHECK_DISPLAY(dpy);
+ ctx = CTX(dpy);
+ if (!ctx)
+ return VA_STATUS_ERROR_INVALID_DISPLAY;
+
+ if (!ctx->vtable->vaQuerySurfaceAttributes)
+ vaStatus = va_impl_query_surface_attributes(ctx, config,
+ attrib_list, num_attribs);
+ else
+ vaStatus = ctx->vtable->vaQuerySurfaceAttributes(ctx, config,
+ attrib_list, num_attribs);
+
+ VA_TRACE_LOG(va_TraceQuerySurfaceAttributes, dpy, config, attrib_list, num_attribs);
+
+ return vaStatus;
+}
+
+VAStatus
+vaCreateSurfaces(
+ VADisplay dpy,
+ unsigned int format,
+ unsigned int width,
+ unsigned int height,
+ VASurfaceID *surfaces,
+ unsigned int num_surfaces,
+ VASurfaceAttrib *attrib_list,
+ unsigned int num_attribs
+)
+{
+ VADriverContextP ctx;
+ VAStatus vaStatus;
+
+ CHECK_DISPLAY(dpy);
+ ctx = CTX(dpy);
+ if (!ctx)
+ return VA_STATUS_ERROR_INVALID_DISPLAY;
+
+ if (ctx->vtable->vaCreateSurfaces2)
+ vaStatus = ctx->vtable->vaCreateSurfaces2(ctx, format, width, height,
+ surfaces, num_surfaces,
+ attrib_list, num_attribs);
+ else if (attrib_list && num_attribs > 0)
+ vaStatus = VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
+ else
+ vaStatus = ctx->vtable->vaCreateSurfaces(ctx, width, height, format,
+ num_surfaces, surfaces);
+ VA_TRACE_LOG(va_TraceCreateSurfaces,
+ dpy, width, height, format, num_surfaces, surfaces,
+ attrib_list, num_attribs);
+
+ return vaStatus;