1 /*
2 * Copyright (C) 2012 Intel Corporation. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #include "sysdeps.h"
26
27 #include <va/va_dricommon.h>
28
29 #include "i965_drv_video.h"
30 #include "i965_output_dri.h"
31 #include "dso_utils.h"
32
33 #define LIBVA_X11_NAME "libva-x11.so.2"
34
35 typedef struct dri_drawable *(*dri_get_drawable_func)(VADriverContextP ctx, XID drawable);
36 typedef union dri_buffer *(*dri_get_rendering_buffer_func)(VADriverContextP ctx, struct dri_drawable *d);
37 typedef void (*dri_swap_buffer_func)(VADriverContextP ctx, struct dri_drawable *d);
38
39 struct dri_vtable {
40 dri_get_drawable_func get_drawable;
41 dri_get_rendering_buffer_func get_rendering_buffer;
42 dri_swap_buffer_func swap_buffer;
43 };
44
45 struct va_dri_output {
46 struct dso_handle *handle;
47 struct dri_vtable vtable;
48 };
49
50 bool
i965_output_dri_init(VADriverContextP ctx)51 i965_output_dri_init(VADriverContextP ctx)
52 {
53 struct i965_driver_data * const i965 = i965_driver_data(ctx);
54 struct dso_handle *dso_handle;
55 struct dri_vtable *dri_vtable;
56
57 static const struct dso_symbol symbols[] = {
58 {
59 "va_dri_get_drawable",
60 offsetof(struct dri_vtable, get_drawable)
61 },
62 {
63 "va_dri_get_rendering_buffer",
64 offsetof(struct dri_vtable, get_rendering_buffer)
65 },
66 {
67 "va_dri_swap_buffer",
68 offsetof(struct dri_vtable, swap_buffer)
69 },
70 { NULL, }
71 };
72
73 i965->dri_output = calloc(1, sizeof(struct va_dri_output));
74 if (!i965->dri_output)
75 goto error;
76
77 i965->dri_output->handle = dso_open(LIBVA_X11_NAME);
78 if (!i965->dri_output->handle)
79 goto error;
80
81 dso_handle = i965->dri_output->handle;
82 dri_vtable = &i965->dri_output->vtable;
83 if (!dso_get_symbols(dso_handle, dri_vtable, sizeof(*dri_vtable), symbols))
84 goto error;
85 return true;
86
87 error:
88 i965_output_dri_terminate(ctx);
89 return false;
90 }
91
92 void
i965_output_dri_terminate(VADriverContextP ctx)93 i965_output_dri_terminate(VADriverContextP ctx)
94 {
95 struct i965_driver_data * const i965 = i965_driver_data(ctx);
96 struct va_dri_output * const dri_output = i965->dri_output;
97
98 if (!dri_output)
99 return;
100
101 if (dri_output->handle) {
102 dso_close(dri_output->handle);
103 dri_output->handle = NULL;
104 }
105
106 free(dri_output);
107 i965->dri_output = NULL;
108 }
109
110 VAStatus
i965_put_surface_dri(VADriverContextP ctx,VASurfaceID surface,void * draw,const VARectangle * src_rect,const VARectangle * dst_rect,const VARectangle * cliprects,unsigned int num_cliprects,unsigned int flags)111 i965_put_surface_dri(
112 VADriverContextP ctx,
113 VASurfaceID surface,
114 void *draw,
115 const VARectangle *src_rect,
116 const VARectangle *dst_rect,
117 const VARectangle *cliprects,
118 unsigned int num_cliprects,
119 unsigned int flags
120 )
121 {
122 struct i965_driver_data * const i965 = i965_driver_data(ctx);
123 struct dri_vtable * const dri_vtable = &i965->dri_output->vtable;
124 struct i965_render_state * const render_state = &i965->render_state;
125 struct dri_drawable *dri_drawable;
126 union dri_buffer *buffer;
127 struct intel_region *dest_region;
128 struct object_surface *obj_surface;
129 uint32_t name;
130 int i, ret;
131
132 /* Currently don't support DRI1 */
133 if (!VA_CHECK_DRM_AUTH_TYPE(ctx, VA_DRM_AUTH_DRI2))
134 return VA_STATUS_ERROR_UNKNOWN;
135
136 /* Some broken sources such as H.264 conformance case FM2_SVA_C
137 * will get here
138 */
139 obj_surface = SURFACE(surface);
140 ASSERT_RET(obj_surface && obj_surface->bo, VA_STATUS_SUCCESS);
141 ASSERT_RET(obj_surface->fourcc != VA_FOURCC_YUY2 &&
142 obj_surface->fourcc != VA_FOURCC_UYVY &&
143 obj_surface->fourcc != VA_FOURCC_RGBX &&
144 obj_surface->fourcc != VA_FOURCC_BGRX,
145 VA_STATUS_ERROR_UNIMPLEMENTED);
146
147 _i965LockMutex(&i965->render_mutex);
148
149 dri_drawable = dri_vtable->get_drawable(ctx, (Drawable)draw);
150 ASSERT_RET(dri_drawable, VA_STATUS_ERROR_ALLOCATION_FAILED);
151
152 buffer = dri_vtable->get_rendering_buffer(ctx, dri_drawable);
153 ASSERT_RET(buffer, VA_STATUS_ERROR_ALLOCATION_FAILED);
154
155 dest_region = render_state->draw_region;
156 if (dest_region == NULL) {
157 dest_region = (struct intel_region *)calloc(1, sizeof(*dest_region));
158 ASSERT_RET(dest_region, VA_STATUS_ERROR_ALLOCATION_FAILED);
159 render_state->draw_region = dest_region;
160 }
161
162 if (dest_region->bo) {
163 dri_bo_flink(dest_region->bo, &name);
164 if (buffer->dri2.name != name) {
165 dri_bo_unreference(dest_region->bo);
166 dest_region->bo = NULL;
167 }
168 }
169
170 if (dest_region->bo == NULL) {
171 dest_region->cpp = buffer->dri2.cpp;
172 dest_region->pitch = buffer->dri2.pitch;
173
174 dest_region->bo = intel_bo_gem_create_from_name(i965->intel.bufmgr, "rendering buffer", buffer->dri2.name);
175 ASSERT_RET(dest_region->bo, VA_STATUS_ERROR_UNKNOWN);
176
177 ret = dri_bo_get_tiling(dest_region->bo, &(dest_region->tiling), &(dest_region->swizzle));
178 ASSERT_RET((ret == 0), VA_STATUS_ERROR_UNKNOWN);
179 }
180
181 dest_region->x = dri_drawable->x;
182 dest_region->y = dri_drawable->y;
183 dest_region->width = dri_drawable->width;
184 dest_region->height = dri_drawable->height;
185
186 if (!(flags & VA_SRC_COLOR_MASK))
187 flags |= VA_SRC_BT601;
188
189 intel_render_put_surface(ctx, obj_surface, src_rect, dst_rect, flags);
190
191 for (i = 0; i < I965_MAX_SUBPIC_SUM; i++) {
192 if (obj_surface->obj_subpic[i] != NULL) {
193 assert(obj_surface->subpic[i] != VA_INVALID_ID);
194 obj_surface->subpic_render_idx = i;
195 intel_render_put_subpicture(ctx, obj_surface, src_rect, dst_rect);
196 }
197 }
198
199 if (!(g_intel_debug_option_flags & VA_INTEL_DEBUG_OPTION_BENCH))
200 dri_vtable->swap_buffer(ctx, dri_drawable);
201
202 _i965UnlockMutex(&i965->render_mutex);
203
204 return VA_STATUS_SUCCESS;
205 }
206