1 /*
2 * Copyright (c) 2011 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 * Authors:
25 * Shengquan Yuan <shengquan.yuan@intel.com>
26 * Zhaohan Ren <zhaohan.ren@intel.com>
27 *
28 */
29
30
31 #include <va/va_backend.h>
32 #include "psb_surface.h"
33 #include "psb_output.h"
34 #include "psb_surface_ext.h"
35 #include "psb_x11.h"
36 #include "psb_xrandr.h"
37 #include "psb_drv_debug.h"
38
39 #include <X11/extensions/dpms.h>
40
41 #include <wsbm/wsbm_manager.h>
42
43 #define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData;
44 #define INIT_OUTPUT_PRIV psb_x11_output_p output = (psb_x11_output_p)(((psb_driver_data_p)ctx->pDriverData)->ws_priv)
45
46 #define SURFACE(id) ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id ))
47
48 static int psb_CheckDrawable(VADriverContextP ctx, Drawable draw);
49
50 int (*oldHandler)(Display *, XErrorEvent *) = 0;
51 static int XErrorFlag = 1;
psb_XErrorHandler(Display * dpy,XErrorEvent * event)52 static int psb_XErrorHandler(Display *dpy, XErrorEvent *event)
53 {
54 drv_debug_msg(VIDEO_DEBUG_GENERAL, "XErrorEvent caught in psb_XErrorHandler in psb_xvva.c\n");
55 if (event->type == 0 && event->request_code == 132 && event->error_code == 11 /* BadAlloc */) {
56 XErrorFlag = 1;
57 return 0;
58 }
59 return oldHandler(dpy, event);
60 }
61
GetPortId(VADriverContextP ctx,psb_x11_output_p output)62 static int GetPortId(VADriverContextP ctx, psb_x11_output_p output)
63 {
64 int i, j, k;
65 unsigned int numAdapt;
66 int numImages;
67 XvImageFormatValues *formats;
68 XvAdaptorInfo *info;
69 int ret, grab_ret;
70 Display *dpy = (Display *)ctx->native_dpy;
71
72 ret = XvQueryAdaptors(dpy, DefaultRootWindow(dpy), &numAdapt, &info);
73 /*Force overlay port num equal to one. OverlayC can't be used independently now.*/
74 /* check for numAdapt before modifying the info[1]. Without this check
75 * it will cause a memory corruption leading to segfaults */
76 if (numAdapt > 1)
77 info[1].num_ports = 1;
78
79 if (Success != ret) {
80 drv_debug_msg(VIDEO_DEBUG_ERROR, "Can't find Xvideo adaptor\n");
81 return -1;
82 }
83
84 grab_ret = XGrabServer(ctx->native_dpy);
85 for (i = 0; i < numAdapt; i++) {
86 if ((info[i].type & XvImageMask) == 0)
87 continue;
88
89 formats = XvListImageFormats(dpy, info[i].base_id, &numImages);
90 for (j = 0; j < numImages; j++) {
91 if (formats[j].id != FOURCC_XVVA) continue;
92 for (k = 0; k < info[i].num_ports; k++) {
93 int ret = XvGrabPort(dpy, info[i].base_id + k, CurrentTime);
94
95 if (Success == ret) {
96 /* for textured adaptor 0 */
97 if (i == 0)
98 output->textured_portID = info[i].base_id + k;
99 /* for overlay adaptor 1 */
100 if (i == 1)
101 output->overlay_portID = info[i].base_id + k;
102 break;
103 }
104 }
105 }
106 XFree(formats);
107 }
108
109 if (grab_ret != 0)
110 XUngrabServer(ctx->native_dpy);
111
112 if ((output->textured_portID == 0) && (output->overlay_portID == 0)) {
113 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Can't detect any usable Xv XVVA port\n");
114 return -1;
115 }
116
117 return 0;
118 }
119
120
psb_init_xvideo(VADriverContextP ctx,psb_x11_output_p output)121 VAStatus psb_init_xvideo(VADriverContextP ctx, psb_x11_output_p output)
122 {
123 #ifdef _FOR_FPGA_
124 return VA_STATUS_SUCCESS;
125 #endif
126
127 INIT_DRIVER_DATA;
128 int dummy, ret;
129
130 output->textured_portID = output->overlay_portID = 0;
131 if (GetPortId(ctx, output)) {
132 drv_debug_msg(VIDEO_DEBUG_ERROR, "Grab Xvideo port failed, fallback to software vaPutSurface.\n");
133 return VA_STATUS_ERROR_ALLOCATION_FAILED;
134 }
135
136 if (output->textured_portID)
137 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Detected textured Xvideo port_id = %d.\n", (unsigned int)output->textured_portID);
138 if (output->overlay_portID)
139 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Detected overlay Xvideo port_id = %d.\n", (unsigned int)output->overlay_portID);
140
141 output->sprite_enabled = 0;
142 if (getenv("PSB_SPRITE_ENABLE")) {
143 drv_debug_msg(VIDEO_DEBUG_GENERAL, "use sprite plane to playback rotated protected video\n");
144 output->sprite_enabled = 1;
145 }
146
147 output->ignore_dpm = 1;
148 if (getenv("PSB_VIDEO_DPMS_HACK")) {
149 if (DPMSQueryExtension((Display *)ctx->native_dpy, &dummy, &dummy)
150 && DPMSCapable((Display *)ctx->native_dpy)) {
151 BOOL onoff;
152 CARD16 state;
153
154 DPMSInfo((Display *)ctx->native_dpy, &state, &onoff);
155 drv_debug_msg(VIDEO_DEBUG_GENERAL, "DPMS is %s, monitor state=%s\n", onoff ? "enabled" : "disabled",
156 (state == DPMSModeOn) ? "on" : (
157 (state == DPMSModeOff) ? "off" : (
158 (state == DPMSModeStandby) ? "standby" : (
159 (state == DPMSModeSuspend) ? "suspend" : "unknow"))));
160 if (onoff)
161 output->ignore_dpm = 0;
162 }
163 }
164
165 /* by default, overlay Xv */
166 if (output->textured_portID)
167 driver_data->output_method = PSB_PUTSURFACE_TEXTURE;
168 if (output->overlay_portID)
169 driver_data->output_method = PSB_PUTSURFACE_OVERLAY;
170
171 ret = psb_xrandr_init(ctx);
172 if (ret != 0) {
173 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to initialize psb xrandr error # %d\n", __func__, ret);
174 return VA_STATUS_ERROR_UNKNOWN;
175 }
176
177 return VA_STATUS_SUCCESS;
178 }
179
180
psb_deinit_xvideo(VADriverContextP ctx)181 VAStatus psb_deinit_xvideo(VADriverContextP ctx)
182 {
183 INIT_DRIVER_DATA;
184 INIT_OUTPUT_PRIV;
185
186 if (output->gc) {
187 XFreeGC((Display *)ctx->native_dpy, output->gc);
188 output->gc = NULL;
189 }
190
191 if (output->extend_gc) {
192 XFreeGC((Display *)ctx->native_dpy, output->extend_gc);
193 output->extend_gc = NULL;
194 }
195
196 if (output->textured_xvimage) {
197 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Destroy XvImage for texture Xv\n");
198 XFree(output->textured_xvimage);
199 output->textured_xvimage = NULL;
200 }
201
202 if (output->overlay_xvimage) {
203 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Destroy XvImage for overlay Xv\n");
204 XFree(output->overlay_xvimage);
205 output->textured_xvimage = NULL;
206 }
207
208 if (output->textured_portID) {
209 if ((output->using_port == USING_TEXTURE_PORT) && output->output_drawable
210 && (psb_CheckDrawable(ctx, output->output_drawable) == 0)) {
211 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Deinit: stop textured Xvideo\n");
212 XvStopVideo((Display *)ctx->native_dpy, output->textured_portID, output->output_drawable);
213 }
214
215 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Deinit: ungrab textured Xvideo port\n");
216 XvUngrabPort((Display *)ctx->native_dpy, output->textured_portID, CurrentTime);
217 output->textured_portID = 0;
218 }
219
220 if (output->overlay_portID) {
221 if ((output->using_port == USING_OVERLAY_PORT) && output->output_drawable
222 && (psb_CheckDrawable(ctx, output->output_drawable) == 0)) {
223 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Deinit: stop overlay Xvideo\n");
224 XvStopVideo((Display *)ctx->native_dpy, output->overlay_portID, output->output_drawable);
225 }
226
227 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Deinit: ungrab overlay Xvideo port\n");
228 XvUngrabPort((Display *)ctx->native_dpy, output->overlay_portID, CurrentTime);
229 output->overlay_portID = 0;
230 }
231
232 if (driver_data->use_xrandr_thread && driver_data->xrandr_thread_id) {
233 psb_xrandr_thread_exit();
234 pthread_join(driver_data->xrandr_thread_id, NULL);
235 driver_data->xrandr_thread_id = 0;
236 }
237 psb_xrandr_deinit();
238
239 output->using_port = 0;
240 output->output_drawable = 0;
241 output->extend_drawable = 0;
242 #ifndef _FOR_FPGA_
243 XSync((Display *)ctx->native_dpy, False);
244 #endif
245 return VA_STATUS_SUCCESS;
246 }
247
248
psb_surface_init(psb_driver_data_p driver_data,PsbVASurfaceRec * srf,int fourcc,int bpp,int w,int h,int stride,int size,unsigned int pre_add,struct _WsbmBufferObject * bo,int flags)249 static void psb_surface_init(
250 psb_driver_data_p driver_data,
251 PsbVASurfaceRec *srf,
252 int fourcc, int bpp, int w, int h, int stride, int size, unsigned int pre_add,
253 struct _WsbmBufferObject *bo, int flags
254 )
255 {
256 memset(srf, 0, sizeof(*srf));
257
258 srf->fourcc = fourcc;
259 srf->bo = bo;
260 if (bo != NULL) {
261 srf->bufid = wsbmKBufHandle(wsbmKBuf(bo));
262 srf->pl_flags = wsbmBOPlacementHint(bo);
263 }
264
265 /*
266 if (srf->pl_flags & DRM_PSB_FLAG_MEM_CI)
267 srf->reserved_phyaddr = driver_data->camera_phyaddr;
268 if (srf->pl_flags & DRM_PSB_FLAG_MEM_RAR)
269 srf->reserved_phyaddr = driver_data->rar_phyaddr;
270 */
271 srf->bytes_pp = bpp;
272
273 srf->width = w;
274 srf->pre_add = pre_add;
275 if ((flags == VA_TOP_FIELD) || (flags == VA_BOTTOM_FIELD)) {
276 if (driver_data->output_method == PSB_PUTSURFACE_FORCE_OVERLAY
277 || driver_data->output_method == PSB_PUTSURFACE_OVERLAY) {
278 srf->height = h;
279 srf->stride = stride;
280 } else {
281 srf->height = h / 2;
282 srf->stride = stride * 2;
283 }
284 if (flags == VA_BOTTOM_FIELD)
285 srf->pre_add += stride;
286 } else {
287 srf->height = h;
288 srf->stride = stride;
289 }
290
291 srf->size = size;
292
293 if (flags == VA_CLEAR_DRAWABLE) {
294 srf->clear_color = driver_data->clear_color; /* color */
295 return;
296 }
297 }
298
299 #if 0
300
301 #define WINDOW 1
302 #define PIXMAP 0
303
304 /* return 0 for no rotation, 1 for rotation occurs */
305 /* XRRGetScreenInfo has significant performance drop */
306 static int psb__CheckCurrentRotation(VADriverContextP ctx)
307 {
308 Rotation current_rotation;
309 XRRScreenConfiguration *scrn_cfg;
310 scrn_cfg = XRRGetScreenInfo((Display *)ctx->native_dpy, DefaultRootWindow((Display *)ctx->native_dpy));
311 XRRConfigCurrentConfiguration(scrn_cfg, ¤t_rotation);
312 XRRFreeScreenConfigInfo(scrn_cfg);
313 return (current_rotation & 0x0f);
314 }
315
316 /* Check drawable type, 1 for window, 0 for pixmap
317 * Have significant performance drop in XFCE environment
318 */
319 static void psb__CheckDrawableType(Display *dpy, Window win, Drawable draw, int *type_ret)
320 {
321
322 unsigned int child_num;
323 Window root_return;
324 Window parent_return;
325 Window *child_return;
326 int i;
327
328 if (win == draw) {
329 *type_ret = 1;
330 return;
331 }
332
333 XQueryTree(dpy, win, &root_return, &parent_return, &child_return, &child_num);
334
335 if (!child_num)
336 return;
337
338 for (i = 0; i < child_num; i++)
339 psb__CheckDrawableType(dpy, child_return[i], draw, type_ret);
340 }
341 #endif
342
343
psb_CheckDrawable(VADriverContextP ctx,Drawable draw)344 static int psb_CheckDrawable(VADriverContextP ctx, Drawable draw)
345 {
346 INIT_DRIVER_DATA;
347 INIT_OUTPUT_PRIV;
348 Atom xvDrawable = XInternAtom((Display *)ctx->native_dpy, "XV_DRAWABLE", 0);
349 int val = 0;
350
351 driver_data->drawable_info = 0;
352 if (output->overlay_portID) {
353 XvSetPortAttribute((Display *)ctx->native_dpy, output->overlay_portID, xvDrawable, draw);
354 XvGetPortAttribute((Display *)ctx->native_dpy, output->overlay_portID, xvDrawable, &val);
355 } else if (output->textured_portID) {
356 XvSetPortAttribute((Display *)ctx->native_dpy, output->textured_portID, xvDrawable, draw);
357 XvGetPortAttribute((Display *)ctx->native_dpy, output->textured_portID, xvDrawable, &val);
358 }
359 driver_data->drawable_info = val;
360
361 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Get xvDrawable = 0x%08x\n", val);
362
363 if (driver_data->drawable_info == XVDRAWABLE_INVALID_DRAWABLE)
364 return -1;
365
366 return 0;
367 }
368
psb__CheckPutSurfaceXvPort(VADriverContextP ctx,VASurfaceID surface,Drawable draw,short srcx,short srcy,unsigned short srcw,unsigned short srch,short destx,short desty,unsigned short destw,unsigned short desth,VARectangle * cliprects,unsigned int number_cliprects,unsigned int flags)369 static int psb__CheckPutSurfaceXvPort(
370 VADriverContextP ctx,
371 VASurfaceID surface,
372 Drawable draw, /* X Drawable */
373 short srcx,
374 short srcy,
375 unsigned short srcw,
376 unsigned short srch,
377 short destx,
378 short desty,
379 unsigned short destw,
380 unsigned short desth,
381 VARectangle *cliprects, /* client supplied clip list */
382 unsigned int number_cliprects, /* number of clip rects in the clip list */
383 unsigned int flags /* de-interlacing flags */
384 )
385 {
386 INIT_DRIVER_DATA;
387 INIT_OUTPUT_PRIV;
388 object_surface_p obj_surface = SURFACE(surface);
389 uint32_t buf_pl;
390
391 /* silent klockwork */
392 if (obj_surface && obj_surface->psb_surface)
393 buf_pl = obj_surface->psb_surface->buf.pl_flags;
394 else
395 return -1;
396
397 if (flags & VA_CLEAR_DRAWABLE)
398 return 0;
399
400 if (output->overlay_portID == 0) { /* no overlay usable */
401 driver_data->output_method = PSB_PUTSURFACE_TEXTURE;
402 return 0;
403 }
404
405 if (driver_data->output_method == PSB_PUTSURFACE_FORCE_OVERLAY) {
406 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Force Overlay Xvideo for PutSurface\n");
407 return 0;
408 }
409
410 if ((driver_data->output_method == PSB_PUTSURFACE_FORCE_TEXTURE)) {
411 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Force Textured Xvideo for PutSurface\n");
412 return 0;
413 }
414
415 if (((buf_pl & (WSBM_PL_FLAG_TT)) == 0) /* buf not in TT/RAR or CI */
416 || (obj_surface->width > 1920) /* overlay have isue to support >1920xXXX resolution */
417 || (obj_surface->subpic_count > 0) /* overlay can't support subpicture */
418 /* || (flags & (VA_TOP_FIELD|VA_BOTTOM_FIELD))*/
419 ) {
420 driver_data->output_method = PSB_PUTSURFACE_TEXTURE;
421 return 0;
422 }
423
424
425 /* Here should be overlay XV by defaut after overlay is stable */
426 driver_data->output_method = PSB_PUTSURFACE_OVERLAY;
427 /* driver_data->output_method = PSB_PUTSURFACE_TEXTURE; */
428
429 /*
430 *Query Overlay Adaptor by XvDrawable Attribute to know current
431 * Xrandr information:rotation/downscaling
432 * also set target drawable(window vs pixmap) into XvDrawable
433 * to levage Xserver to determiate it is Pixmap or Window
434 */
435 /*
436 *ROTATE_90: 0x2, ROTATE_180: 0x4, ROTATE_270:0x8
437 *Overlay adopator can support video rotation,
438 *but its performance is lower than texture video path.
439 *When video protection and rotation are required (use RAR buffer),
440 *only overlay adaptor will be used.
441 *other attribute like down scaling and pixmap, use texture adaptor
442 */
443 if (driver_data->drawable_info
444 & (XVDRAWABLE_ROTATE_180 | XVDRAWABLE_ROTATE_90 | XVDRAWABLE_ROTATE_270)) {
445 driver_data->output_method = PSB_PUTSURFACE_TEXTURE;
446 }
447
448 if (driver_data->drawable_info & (XVDRAWABLE_PIXMAP | XVDRAWABLE_REDIRECT_WINDOW))
449 driver_data->output_method = PSB_PUTSURFACE_TEXTURE;
450
451 if (srcw >= destw * 8 || srch >= desth * 8)
452 driver_data->output_method = PSB_PUTSURFACE_TEXTURE;
453
454 return 0;
455 }
456
457
psb__CheckGCXvImage(VADriverContextP ctx,VASurfaceID surface,Drawable draw,XvImage ** xvImage,XvPortID * port_id,unsigned int flags)458 static int psb__CheckGCXvImage(
459 VADriverContextP ctx,
460 VASurfaceID surface,
461 Drawable draw,
462 XvImage **xvImage,
463 XvPortID *port_id,
464 unsigned int flags /* de-interlacing flags */
465 )
466 {
467 INIT_DRIVER_DATA;
468 INIT_OUTPUT_PRIV;
469 object_surface_p obj_surface = SURFACE(surface); /* surface already checked */
470
471 if (output->output_drawable != draw) {
472 if (output->gc)
473 XFreeGC((Display *)ctx->native_dpy, output->gc);
474 output->gc = XCreateGC((Display *)ctx->native_dpy, draw, 0, NULL);
475 output->output_drawable = draw;
476 }
477
478 if (flags & VA_CLEAR_DRAWABLE) {
479 if (output->textured_portID && (output->using_port == USING_TEXTURE_PORT)) {
480 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clear drawable, and stop textured Xvideo\n");
481 XvStopVideo((Display *)ctx->native_dpy, output->textured_portID, draw);
482 }
483
484 if (output->overlay_portID && (output->using_port == USING_OVERLAY_PORT)) {
485 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clear drawable, and stop overlay Xvideo\n");
486 XvStopVideo((Display *)ctx->native_dpy, output->overlay_portID, draw);
487 }
488
489 output->using_port = 0;
490
491 XSetForeground((Display *)ctx->native_dpy, output->gc, driver_data->clear_color);
492
493 return 0;
494 }
495
496 if ((driver_data->output_method == PSB_PUTSURFACE_FORCE_OVERLAY) ||
497 (driver_data->output_method == PSB_PUTSURFACE_OVERLAY)) {
498 /* use OVERLAY XVideo */
499 if (obj_surface &&
500 ((output->output_width != obj_surface->width) ||
501 (output->output_height != obj_surface->height) ||
502 (!output->overlay_xvimage))) {
503
504 if (output->overlay_xvimage)
505 XFree(output->overlay_xvimage);
506
507 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create new XvImage for overlay\n");
508 output->overlay_xvimage = XvCreateImage((Display *)ctx->native_dpy, output->overlay_portID,
509 FOURCC_XVVA, 0,
510 obj_surface->width, obj_surface->height);
511
512 output->overlay_xvimage->data = (char *) & output->imgdata_vasrf;
513 output->output_width = obj_surface->width;
514 output->output_height = obj_surface->height;
515 }
516 *xvImage = output->overlay_xvimage;
517 *port_id = output->overlay_portID;
518
519 if ((output->textured_portID) && (output->using_port == USING_TEXTURE_PORT)) { /* stop texture port */
520 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Using overlay xvideo, stop textured xvideo\n");
521 XvStopVideo((Display *)ctx->native_dpy, output->textured_portID, draw);
522 XSync((Display *)ctx->native_dpy, False);
523 }
524 output->using_port = USING_OVERLAY_PORT;
525
526 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Using Overlay Xvideo (%d) for PutSurface\n", output->textured_portID);
527
528 return 0;
529 }
530
531 if ((driver_data->output_method == PSB_PUTSURFACE_FORCE_TEXTURE) ||
532 (driver_data->output_method == PSB_PUTSURFACE_TEXTURE)) {
533 /* use Textured XVideo */
534 if (obj_surface &&
535 ((output->output_width != obj_surface->width) ||
536 (output->output_height != obj_surface->height ||
537 (!output->textured_xvimage)))) {
538 if (output->textured_xvimage)
539 XFree(output->textured_xvimage);
540
541 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Create new XvImage for overlay\n");
542 output->textured_xvimage = XvCreateImage((Display *)ctx->native_dpy, output->textured_portID, FOURCC_XVVA, 0,
543 obj_surface->width, obj_surface->height);
544 output->textured_xvimage->data = (char *) & output->imgdata_vasrf;
545 output->output_width = obj_surface->width;
546 output->output_height = obj_surface->height;
547
548 }
549
550 *xvImage = output->textured_xvimage;
551 *port_id = output->textured_portID;
552
553 if ((output->overlay_portID) && (output->using_port == USING_OVERLAY_PORT)) { /* stop overlay port */
554 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Using textured xvideo, stop Overlay xvideo\n");
555 XvStopVideo((Display *)ctx->native_dpy, output->overlay_portID, draw);
556 XSync((Display *)ctx->native_dpy, False);
557
558 output->using_port = USING_TEXTURE_PORT;
559 }
560
561 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Using Texture Xvideo (%d) for PutSurface\n", output->textured_portID);
562
563 return 0;
564 }
565
566 return 0;
567 }
568
psb_force_dpms_on(VADriverContextP ctx)569 static int psb_force_dpms_on(VADriverContextP ctx)
570 {
571 BOOL onoff;
572 CARD16 state;
573
574 DPMSInfo((Display *)ctx->native_dpy, &state, &onoff);
575 drv_debug_msg(VIDEO_DEBUG_GENERAL, "DPMS is %s, monitor state=%s\n", onoff ? "enabled" : "disabled",
576 (state == DPMSModeOn) ? "on" : (
577 (state == DPMSModeOff) ? "off" : (
578 (state == DPMSModeStandby) ? "standby" : (
579 (state == DPMSModeSuspend) ? "suspend" : "unknow"))));
580 if (onoff && (state != DPMSModeOn)) {
581 drv_debug_msg(VIDEO_DEBUG_GENERAL, "DPMS is enabled, and monitor isn't DPMSModeOn, force it on\n");
582 DPMSForceLevel((Display *)ctx->native_dpy, DPMSModeOn);
583 }
584
585 return 0;
586 }
587
psb_check_rotatesurface(VADriverContextP ctx,unsigned short rotate_width,unsigned short rotate_height,unsigned int protected,int fourcc)588 VAStatus psb_check_rotatesurface(
589 VADriverContextP ctx,
590 unsigned short rotate_width,
591 unsigned short rotate_height,
592 unsigned int protected,
593 int fourcc
594 )
595 {
596 INIT_DRIVER_DATA;
597 INIT_OUTPUT_PRIV;
598 VAStatus vaStatus = VA_STATUS_SUCCESS;
599 object_surface_p obj_rotate_surface;
600 unsigned int flags = protected? IS_PROTECTED : 0;
601
602 if (output->rotate_surface) {
603 obj_rotate_surface = SURFACE(output->rotate_surfaceID);
604 if (obj_rotate_surface &&
605 ((obj_rotate_surface->width != rotate_width)
606 || (obj_rotate_surface->height != rotate_height))) {
607 psb_surface_destroy(output->rotate_surface);
608 free(output->rotate_surface);
609 object_heap_free(&driver_data->surface_heap, (object_base_p)obj_rotate_surface);
610 output->rotate_surface = NULL;
611 }
612 }
613 if (output->rotate_surface == NULL) {
614 output->rotate_surfaceID = object_heap_allocate(&driver_data->surface_heap);
615 obj_rotate_surface = SURFACE(output->rotate_surfaceID);
616 if (NULL == obj_rotate_surface) {
617 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
618 DEBUG_FAILURE;
619
620 return VA_STATUS_ERROR_ALLOCATION_FAILED;
621 }
622
623 obj_rotate_surface->surface_id = output->rotate_surfaceID;
624 obj_rotate_surface->context_id = -1;
625 obj_rotate_surface->width = rotate_width;
626 obj_rotate_surface->height = rotate_height;
627 obj_rotate_surface->subpictures = NULL;
628 obj_rotate_surface->subpic_count = 0;
629 obj_rotate_surface->derived_imgcnt = 0;
630 output->rotate_surface = (psb_surface_p) calloc(1, sizeof(struct psb_surface_s));
631 if (NULL == output->rotate_surface) {
632 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_rotate_surface);
633 obj_rotate_surface->surface_id = VA_INVALID_SURFACE;
634
635 vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED;
636
637 DEBUG_FAILURE;
638
639 return VA_STATUS_ERROR_ALLOCATION_FAILED;
640 }
641
642 flags |= IS_ROTATED;
643 vaStatus = psb_surface_create(driver_data, rotate_width, rotate_height,
644 fourcc, flags, output->rotate_surface);
645 if (VA_STATUS_SUCCESS != vaStatus) {
646 free(obj_rotate_surface->psb_surface);
647 object_heap_free(&driver_data->surface_heap, (object_base_p) obj_rotate_surface);
648 obj_rotate_surface->surface_id = VA_INVALID_SURFACE;
649
650 DEBUG_FAILURE;
651 return vaStatus;
652 }
653 obj_rotate_surface->psb_surface = output->rotate_surface;
654 }
655 return vaStatus;
656 }
657
psb_putsurface_xvideo(VADriverContextP ctx,VASurfaceID surface,Drawable draw,short srcx,short srcy,unsigned short srcw,unsigned short srch,short destx,short desty,unsigned short destw,unsigned short desth,VARectangle * cliprects,unsigned int number_cliprects,unsigned int flags)658 VAStatus psb_putsurface_xvideo(
659 VADriverContextP ctx,
660 VASurfaceID surface,
661 Drawable draw,
662 short srcx,
663 short srcy,
664 unsigned short srcw,
665 unsigned short srch,
666 short destx,
667 short desty,
668 unsigned short destw,
669 unsigned short desth,
670 VARectangle *cliprects, /* client supplied clip list */
671 unsigned int number_cliprects, /* number of clip rects in the clip list */
672 unsigned int flags /* de-interlacing flags */
673 )
674 {
675 INIT_DRIVER_DATA;
676 INIT_OUTPUT_PRIV;
677 VAStatus vaStatus = VA_STATUS_SUCCESS;
678 PsbVASurfaceRec *subpic_surface;
679 PsbXvVAPutSurfacePtr vaPtr;
680 XvPortID portID = 0;
681 XvImage *xvImage = NULL;
682 object_surface_p obj_surface = SURFACE(surface);
683 psb_surface_p psb_surface;
684 int i = 0, j;
685
686
687 if (obj_surface) /* silent klockwork, we already check it */
688 psb_surface = obj_surface->psb_surface;
689 else
690 return VA_STATUS_ERROR_UNKNOWN;
691
692 /* Catch X protocol errors with our own error handler */
693 if (oldHandler == 0)
694 oldHandler = XSetErrorHandler(psb_XErrorHandler);
695
696 if (XErrorFlag == 1) {
697 if (psb_CheckDrawable(ctx, draw) != 0) {
698 drv_debug_msg(VIDEO_DEBUG_ERROR, "vaPutSurface: invalidate drawable\n");
699 return VA_STATUS_ERROR_UNKNOWN;
700 }
701
702 drv_debug_msg(VIDEO_DEBUG_GENERAL, "ran psb_CheckDrawable the first time!\n");
703 XErrorFlag = 0;
704 }
705
706 /* check display configuration for every 100 frames */
707 if ((driver_data->frame_count % 100) == 0) {
708 if (psb_CheckDrawable(ctx, draw) != 0) {
709 drv_debug_msg(VIDEO_DEBUG_ERROR, "vaPutSurface: invalidate drawable\n");
710 return VA_STATUS_ERROR_UNKNOWN;
711 }
712 drv_debug_msg(VIDEO_DEBUG_GENERAL, "ran psb_CheckDrawable the first time!\n");
713 }
714
715
716
717 psb__CheckPutSurfaceXvPort(ctx, surface, draw,
718 srcx, srcy, srcw, srch,
719 destx, desty, destw, desth,
720 cliprects, number_cliprects, flags);
721 psb__CheckGCXvImage(ctx, surface, draw, &xvImage, &portID, flags);
722
723 if (flags & VA_CLEAR_DRAWABLE) {
724 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clean draw with color 0x%08x\n", driver_data->clear_color);
725
726 XFillRectangle((Display *)ctx->native_dpy, draw, output->gc, destx, desty, destw, desth);
727 XSync((Display *)ctx->native_dpy, False);
728
729 XFreeGC((Display *)ctx->native_dpy, output->gc);
730 output->gc = NULL;
731 output->output_drawable = 0;
732
733 XSync((Display *)ctx->native_dpy, False);
734
735 driver_data->cur_displaying_surface = VA_INVALID_SURFACE;
736 driver_data->last_displaying_surface = VA_INVALID_SURFACE;
737 obj_surface->display_timestamp = 0;
738
739
740 return vaStatus;
741 }
742
743 vaPtr = (PsbXvVAPutSurfacePtr)xvImage->data;
744 vaPtr->flags = flags;
745 vaPtr->num_subpicture = obj_surface->subpic_count;
746 vaPtr->num_clipbox = number_cliprects;
747 for (j = 0; j < number_cliprects; j++) {
748 vaPtr->clipbox[j].x = cliprects[j].x;
749 vaPtr->clipbox[j].y = cliprects[j].y;
750 vaPtr->clipbox[j].width = cliprects[j].width;
751 vaPtr->clipbox[j].height = cliprects[j].height;
752 }
753
754 psb_surface_init(driver_data, &vaPtr->src_srf, VA_FOURCC_NV12, 2,
755 obj_surface->width, obj_surface->height,
756 psb_surface->stride, psb_surface->size,
757 psb_surface->buf.buffer_ofs, /* for surface created from RAR/camera device memory
758 * all surfaces share one BO but with different offset
759 * pass the offset as the "pre_add"
760 */
761 psb_surface->buf.drm_buf, flags);
762
763 if ((driver_data->output_method == PSB_PUTSURFACE_OVERLAY)
764 && (driver_data->drawable_info & (XVDRAWABLE_ROTATE_180 | XVDRAWABLE_ROTATE_90 | XVDRAWABLE_ROTATE_270))) {
765 unsigned int rotate_width, rotate_height;
766 int fourcc;
767 if (output->sprite_enabled)
768 fourcc = VA_FOURCC_RGBA;
769 else
770 fourcc = VA_FOURCC_NV12;
771 if (driver_data->drawable_info & (XVDRAWABLE_ROTATE_90 | XVDRAWABLE_ROTATE_270)) {
772 rotate_width = obj_surface->height;
773 rotate_height = obj_surface->width;
774 } else {
775 rotate_width = obj_surface->width;
776 rotate_height = obj_surface->height;
777 }
778 unsigned int protected = vaPtr->src_srf.pl_flags & 0;
779
780 vaStatus = psb_check_rotatesurface(ctx, rotate_width, rotate_height, protected, fourcc);
781 if (VA_STATUS_SUCCESS != vaStatus)
782 return vaStatus;
783
784 psb_surface_init(driver_data, &vaPtr->dst_srf, fourcc, 4,
785 rotate_width, rotate_height,
786 output->rotate_surface->stride, output->rotate_surface->size,
787 output->rotate_surface->buf.buffer_ofs, /* for surface created from RAR/camera device memory
788 * all surfaces share one BO but with different offset
789 * pass the offset as the "pre_add"
790 */
791 output->rotate_surface->buf.drm_buf, 0);
792 }
793 subpic_surface = obj_surface->subpictures;
794 while (subpic_surface) {
795 PsbVASurfaceRec *tmp = &vaPtr->subpic_srf[i++];
796
797 memcpy(tmp, subpic_surface, sizeof(*tmp));
798
799 /* reload palette for paletted subpicture
800 * palete_ptr point to image palette
801 */
802 if (subpic_surface->palette_ptr)
803 memcpy(&tmp->palette[0], subpic_surface->palette_ptr, 16 * sizeof(PsbAYUVSample8));
804
805 subpic_surface = subpic_surface->next;
806 }
807
808 if (output->ignore_dpm == 0)
809 psb_force_dpms_on(ctx);
810
811 XvPutImage((Display *)ctx->native_dpy, portID, draw, output->gc, xvImage,
812 srcx, srcy, srcw, srch, destx, desty, destw, desth);
813 XFlush((Display *)ctx->native_dpy);
814 //XSync((Display *)ctx->native_dpy, False);
815
816 if (portID == output->overlay_portID) {
817 if (driver_data->cur_displaying_surface != VA_INVALID_SURFACE)
818 driver_data->last_displaying_surface = driver_data->cur_displaying_surface;
819 obj_surface->display_timestamp = GetTickCount();
820 driver_data->cur_displaying_surface = surface;
821 } else {
822 driver_data->cur_displaying_surface = VA_INVALID_SURFACE;
823 driver_data->last_displaying_surface = VA_INVALID_SURFACE;
824 obj_surface->display_timestamp = 0;
825 }
826
827
828 return vaStatus;
829 }
830
831