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 * Zhaohan Ren <zhaohan.ren@intel.com>
26 * Shengquan Yuan <shengquan.yuan@intel.com>
27 * Jiang Fei <jiang.fei@intel.com>
28 * Binglin Chen <binglin.chen@intel.com>
29 *
30 */
31 #include <va/va_backend.h>
32 #include "psb_output.h"
33 #include "psb_surface.h"
34 #include "psb_buffer.h"
35 #include "psb_overlay.h"
36 #include "psb_texture.h"
37 #include <stdio.h>
38 #include <string.h>
39 #include <stdarg.h>
40 #include "psb_android_glue.h"
41 #include "psb_output_android.h"
42 #ifndef BAYTRAIL
43 #include "psb_HDMIExtMode.h"
44 #endif
45 #include "pnw_rotate.h"
46 #include "psb_drv_debug.h"
47 #include <wsbm/wsbm_manager.h>
48 #include <hardware.h>
49
50 #define INIT_DRIVER_DATA psb_driver_data_p driver_data = (psb_driver_data_p) ctx->pDriverData;
51 #define INIT_OUTPUT_PRIV psb_android_output_p output = (psb_android_output_p)(((psb_driver_data_p)ctx->pDriverData)->ws_priv)
52
53 #define SURFACE(id) ((object_surface_p) object_heap_lookup( &driver_data->surface_heap, id ))
54 #define BUFFER(id) ((object_buffer_p) object_heap_lookup( &driver_data->buffer_heap, id ))
55 #define IMAGE(id) ((object_image_p) object_heap_lookup( &driver_data->image_heap, id ))
56 #define SUBPIC(id) ((object_subpic_p) object_heap_lookup( &driver_data->subpic_heap, id ))
57 #define CONTEXT(id) ((object_context_p) object_heap_lookup( &driver_data->context_heap, id ))
58
59 #define GET_SURFACE_INFO_rotate(psb_surface) ((int) psb_surface->extra_info[5])
60 #define GET_SURFACE_INFO_protect(psb_surface) ((int) psb_surface->extra_info[6])
61 #define MAX_OVERLAY_IDLE_FRAME 4
62
63 enum {
64 eWidiOff = 1,
65 eWidiClone = 2,
66 eWidiExtendedVideo = 3,
67 };
68 extern unsigned int update_forced;
69
va2hw_rotation(int va_rotate)70 inline int va2hw_rotation(int va_rotate)
71 {
72 switch (va_rotate) {
73 case VA_ROTATION_90:
74 return HAL_TRANSFORM_ROT_270;
75 case VA_ROTATION_180:
76 return HAL_TRANSFORM_ROT_180;
77 case VA_ROTATION_270:
78 return HAL_TRANSFORM_ROT_90;
79 defaut:
80 return 0;
81 }
82
83 return 0;
84 }
85
psb_android_output_init(VADriverContextP ctx)86 unsigned char *psb_android_output_init(VADriverContextP ctx)
87 {
88 INIT_DRIVER_DATA;
89 char put_surface[1024];
90 psb_android_output_p output = calloc(1, sizeof(psb_android_output_s));
91 struct fb_var_screeninfo vinfo;
92 int fbfd = -1;
93
94 if (output == NULL) {
95 drv_debug_msg(VIDEO_DEBUG_ERROR, "Can't malloc memory\n");
96 return NULL;
97 }
98 memset(output, 0, sizeof(psb_android_output_s));
99
100 /* Guess the screen size */
101 output->screen_width = 800;
102 output->screen_height = 480;
103
104 // Open the frame buffer for reading
105 memset(&vinfo, 0, sizeof(vinfo));
106 fbfd = open("/dev/graphics/fb0", O_RDONLY);
107 if (fbfd) {
108 if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo))
109 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Error reading screen information.\n");
110 }
111 close(fbfd);
112 output->screen_width = vinfo.xres;
113 output->screen_height = vinfo.yres;
114
115 /* TS by default */
116 driver_data->output_method = PSB_PUTSURFACE_OVERLAY;
117 driver_data->color_key = 0x000001; /*light blue*/
118
119 if (psb_parse_config("PSB_VIDEO_CTEXTURES", &put_surface[0]) == 0) {
120 drv_debug_msg(VIDEO_DEBUG_GENERAL, "PSB_VIDEO_CTEXTURES is enabled for vaPutSurfaceBuf\n");
121 driver_data->ctexture = 1; /* Init CTEXTURE for vaPutSurfaceBuf */
122 }
123
124 if (psb_parse_config("PSB_VIDEO_COVERLAY", &put_surface[0]) == 0) {
125 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Putsurface use client overlay\n");
126 driver_data->output_method = PSB_PUTSURFACE_FORCE_COVERLAY;
127 }
128
129 driver_data->coverlay = 1;
130
131 return (unsigned char *)output;
132 }
133
psb_android_output_deinit(VADriverContextP ctx)134 VAStatus psb_android_output_deinit(VADriverContextP ctx)
135 {
136 INIT_DRIVER_DATA;
137 INIT_OUTPUT_PRIV;
138 //psb_android_output_p output = GET_OUTPUT_DATA(ctx);
139 #ifdef TARGET_HAS_MULTIPLE_DISPLAY
140 if (output->mds != NULL) {
141 deinit_mds_listener(output);
142 }
143 #endif
144 return VA_STATUS_SUCCESS;
145 }
146
147 #ifndef BAYTRAIL
psb_putsurface_ctexture(VADriverContextP ctx,VASurfaceID surface,unsigned char * data,short srcx,short srcy,unsigned short srcw,unsigned short srch,short destx,short desty,unsigned short destw,unsigned short desth,unsigned int __maybe_unused flags)148 static VAStatus psb_putsurface_ctexture(
149 VADriverContextP ctx,
150 VASurfaceID surface,
151 unsigned char* data,
152 short srcx,
153 short srcy,
154 unsigned short srcw,
155 unsigned short srch,
156 short destx,
157 short desty,
158 unsigned short destw,
159 unsigned short desth,
160 unsigned int __maybe_unused flags /* de-interlacing flags */
161 )
162 {
163 INIT_DRIVER_DATA;
164 INIT_OUTPUT_PRIV;
165 object_surface_p obj_surface;
166 int offset = 0;
167 psb_surface_p psb_surface;
168 VAStatus vaStatus = VA_STATUS_SUCCESS;
169
170 obj_surface = SURFACE(surface);
171 CHECK_SURFACE(obj_surface);
172 psb_surface = obj_surface->psb_surface;
173
174 // psb_surface->buf.drm_buf;
175 // psb_surface->buf.pl_flags;
176 psb_putsurface_textureblit(ctx, data, surface, srcx, srcy, srcw, srch,
177 destx, desty, destw, desth, 0, /* no subtitle */
178 obj_surface->width, obj_surface->height,
179 psb_surface->stride, psb_surface->buf.drm_buf,
180 psb_surface->buf.pl_flags, 1 /* need wrap dst */);
181
182 psb_android_postBuffer(offset);
183
184 return VA_STATUS_SUCCESS;
185 }
186 #endif
187
188 #if 0
189 VAStatus psb_putsurface_coverlay(
190 VADriverContextP ctx,
191 VASurfaceID surface,
192 short srcx,
193 short srcy,
194 unsigned short srcw,
195 unsigned short srch,
196 short destx, /* screen cooridination */
197 short desty,
198 unsigned short destw,
199 unsigned short desth,
200 unsigned int flags /* de-interlacing flags */
201 )
202 {
203 INIT_OUTPUT_PRIV;
204 VAStatus vaStatus = VA_STATUS_SUCCESS;
205
206 /* USE_FIT_SCR_SIZE */
207 /* calculate fit screen size of frame */
208 unsigned short _scr_x = output->screen_width;
209 unsigned short _scr_y = output->screen_height;
210 float _slope_xy = (float)srch / srcw;
211 unsigned short _destw = (short)(_scr_y / _slope_xy);
212 unsigned short _desth = (short)(_scr_x * _slope_xy);
213 short _pos_x, _pos_y;
214
215 if (_destw <= _scr_x) {
216 _desth = _scr_y;
217 _pos_x = (_scr_x - _destw) >> 1;
218 _pos_y = 0;
219 } else {
220 _destw = _scr_x;
221 _pos_x = 0;
222 _pos_y = (_scr_y - _desth) >> 1;
223 }
224 destx += _pos_x;
225 desty += _pos_y;
226 destw = _destw;
227 desth = _desth;
228
229 drv_debug_msg(VIDEO_DEBUG_GENERAL, "psb_putsurface_overlay: src (%d, %d, %d, %d), destx (%d, %d, %d, %d).\n",
230 srcx, srcy, srcw, srch, destx, desty, destw, desth);
231 /* display by overlay */
232 vaStatus = psb_putsurface_overlay(
233 ctx, surface, srcx, srcy, srcw, srch,
234 destx, desty, destw, desth, /* screen coordinate */
235 flags, OVERLAY_A, PIPEA);
236
237 return vaStatus;
238 }
239 #endif
240
241 #if 0
242 static int psb_update_destbox(
243 VADriverContextP ctx
244 )
245 {
246 INIT_DRIVER_DATA;
247 INIT_OUTPUT_PRIV;
248 short destx;
249 short desty;
250 unsigned short destw;
251 unsigned short desth;
252 VAStatus vaStatus = VA_STATUS_SUCCESS;
253
254 psb_android_get_destbox(&destx, &desty, &destw, &desth);
255 /*drv_debug_msg(VIDEO_DEBUG_GENERAL, "destbox = (%d,%d,%d,%d)\n", destx, desty, destw, desth);*/
256 if ((destx >= 0) && (desty >= 0) &&
257 ((destx + destw) <= output->screen_width) &&
258 ((desty + desth) <= output->screen_height) &&
259 (output->destx != destx ||
260 output->desty != desty ||
261 output->destw != destw ||
262 output->desth != desth)) {
263 output->destx = destx;
264 output->desty = desty;
265 output->destw = destw;
266 output->desth = desth;
267 output->new_destbox = 1;
268
269 LOGD("==========New Destbox=============\n");
270 LOGD("output->destbox = (%d,%d,%d,%d)\n", output->destx, output->desty, output->destw, output->desth);
271 }
272
273 return vaStatus;
274 }
275 #endif
276
277 #if 0
278 static int psb_check_outputmethod(
279 VADriverContextP ctx,
280 VASurfaceID surface,
281 unsigned short srcw,
282 unsigned short srch,
283 void *android_isurface,
284 psb_hdmi_mode *hdmi_mode
285 )
286 {
287 INIT_DRIVER_DATA;
288 INIT_OUTPUT_PRIV;
289 psb_HDMIExt_info_p psb_HDMIExt_info = (psb_HDMIExt_info_p)output->psb_HDMIExt_info;
290 object_surface_p obj_surface;
291 int rotation = 0, widi = 0;
292 int delta_rotation = 0;
293 int srf_rotate; /* primary surface rotation */
294 psb_surface_p rotate_surface; /* rotate surface */
295 int rotate_srf_rotate = -1; /* degree of the rotate surface */
296
297 if ((srcw >= 2048) || (srch >= 2048)) {
298 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Clip size extend overlay hw limit, use texstreaming\n");
299 driver_data->output_method = PSB_PUTSURFACE_TEXSTREAMING;
300 return 0;
301 }
302
303 /* use saved status to avoid per-frame checking */
304 if ((driver_data->frame_count % driver_data->outputmethod_checkinterval) != 0) {
305 *hdmi_mode = psb_HDMIExt_get_mode(output);
306 return 0;
307 }
308
309 /* check the status at outputmethod_checkinterval frequency */
310 /* at first check HDMI status */
311 if (psb_HDMIExt_update(ctx, psb_HDMIExt_info)) {
312 drv_debug_msg(VIDEO_DEBUG_ERROR, "%s: Failed to update HDMIExt info.\n", __FUNCTION__);
313 return -1;
314 }
315
316 obj_surface = SURFACE(surface);
317 if (obj_surface == NULL) {
318 drv_debug_msg(VIDEO_DEBUG_ERROR, "Invalid surface\n");
319 return -1;
320 }
321
322 *hdmi_mode = psb_HDMIExt_get_mode(output);
323 if ((*hdmi_mode == EXTENDED_VIDEO) || (*hdmi_mode == CLONE)) {
324 unsigned short _destw, _desth;
325 short _pos_x, _pos_y;
326 unsigned short crtc_width = 0, crtc_height = 0;
327 float _slope_xy;
328
329 /* need to handle VA rotation, and set WM rotate to 0
330 * for Android, MIPI0/HDMI has the same WM rotation always
331 */
332 if (driver_data->mipi0_rotation != 0 || driver_data->rotation_dirty != 0) {
333 driver_data->mipi0_rotation = 0;
334 driver_data->hdmi_rotation = 0;
335 driver_data->rotation_dirty = 0;
336 output->new_destbox = 1;
337 psb_RecalcRotate(ctx, CONTEXT(obj_surface->context_id));
338 }
339
340 psb_HDMIExt_get_prop(output, &crtc_width, &crtc_height);
341
342 /*recalculate the render box to fit the ratio of height/width*/
343 if ((driver_data->extend_rotation == VA_ROTATION_90) ||
344 (driver_data->extend_rotation == VA_ROTATION_270))
345 _slope_xy = (float)srcw / srch;
346 else
347 _slope_xy = (float)srch / srcw;
348
349 _destw = (short)(crtc_height / _slope_xy);
350 _desth = (short)(crtc_width * _slope_xy);
351 if (_destw <= crtc_width) {
352 _desth = crtc_height;
353 _pos_x = (crtc_width - _destw) >> 1;
354 _pos_y = 0;
355 } else {
356 _destw = crtc_width;
357 _pos_x = 0;
358 _pos_y = (crtc_height - _desth) >> 1;
359 }
360 driver_data->render_rect.x = _pos_x;
361 driver_data->render_rect.y = _pos_y;
362 driver_data->render_rect.width = _destw;
363 driver_data->render_rect.height = _desth;
364 drv_debug_msg(VIDEO_DEBUG_GENERAL, "HDMI mode is on (%d), Render Rect: (%d,%d,%d,%d)\n",
365 *hdmi_mode,
366 driver_data->render_rect.x, driver_data->render_rect.y,
367 driver_data->render_rect.width, driver_data->render_rect.height);
368 return 0;
369 }
370
371 /* HDMI is not enabled */
372 psb_android_surfaceflinger_status(android_isurface, &output->sf_composition, &rotation, &widi);
373 /*Update output destbox using layerbuffer's visible region*/
374 psb_update_destbox(ctx);
375
376 if ((driver_data->output_method == PSB_PUTSURFACE_FORCE_COVERLAY)
377 || (driver_data->output_method == PSB_PUTSURFACE_FORCE_TEXSTREAMING))
378 return 0;
379
380 /*If overlay can not get correct destbox, use texstreaming.*/
381 if (output->destw == 0 || output->desth == 0 ||
382 ((output->destw == srcw) && (output->desth == srch))) {
383 drv_debug_msg(VIDEO_DEBUG_GENERAL, "No proper destbox, use texstreaming (%dx%d+%d+%d)\n",
384 output->destw, output->desth, output->destx, output->desty);
385 driver_data->output_method = PSB_PUTSURFACE_TEXSTREAMING;
386 return 0;
387 }
388
389 /* only care local rotation */
390 delta_rotation = Rotation2Angle(driver_data->mipi0_rotation) - Rotation2Angle(rotation);
391 if ((((abs(delta_rotation) == 90) || (abs(delta_rotation) == 270)) && output->new_destbox) ||
392 (abs(delta_rotation) == 180)) {
393 drv_debug_msg(VIDEO_DEBUG_GENERAL, "New rotation degree %d of MIPI0 WM, Need to recalc rotation\n", rotation);
394 driver_data->mipi0_rotation = rotation;
395 driver_data->hdmi_rotation = rotation;
396 driver_data->rotation_dirty |= PSB_NEW_WM_ROTATION;
397 }
398 output->new_destbox = 0;
399
400 if (driver_data->rotation_dirty != 0) {
401 psb_RecalcRotate(ctx, CONTEXT(obj_surface->context_id));
402 driver_data->rotation_dirty = 0;
403 }
404
405 if (GET_SURFACE_INFO_protect(obj_surface->psb_surface)) {
406 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Protected surface, use overlay\n");
407 driver_data->output_method = PSB_PUTSURFACE_COVERLAY;
408
409 return 0;
410 }
411
412 if (widi == eWidiClone) {
413 drv_debug_msg(VIDEO_DEBUG_GENERAL, "WIDI in clone mode, use texstreaming\n");
414 driver_data->output_method = PSB_PUTSURFACE_TEXSTREAMING;
415 driver_data->msvdx_rotate_want = 0;/* disable msvdx rotae */
416
417 return 0;
418 }
419 if (widi == eWidiExtendedVideo) {
420 drv_debug_msg(VIDEO_DEBUG_GENERAL, "WIDI in extend video mode, disable local displaying\n");
421 driver_data->output_method = PSB_PUTSURFACE_NONE;
422 driver_data->msvdx_rotate_want = 0;/* disable msvdx rotae */
423
424 return 0;
425 }
426
427 if (output->sf_composition) {
428 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Composition is detected, use texstreaming\n");
429 driver_data->output_method = PSB_PUTSURFACE_TEXSTREAMING;
430 return 0;
431 }
432
433 srf_rotate = GET_SURFACE_INFO_rotate(obj_surface->psb_surface);
434 rotate_surface = obj_surface->out_loop_surface;
435 if (rotate_surface != NULL)
436 rotate_srf_rotate = GET_SURFACE_INFO_rotate(rotate_surface);
437
438 drv_debug_msg(VIDEO_DEBUG_GENERAL, "SF rotation %d, VA rotation %d, final MSVDX rotation %d\n",
439 rotation, driver_data->va_rotate, driver_data->local_rotation);
440 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Primary surface rotation %d, rotated surface rotation %d\n",
441 srf_rotate, rotate_srf_rotate);
442
443 /* The surface rotation is not same with the final rotation */
444 if ((driver_data->local_rotation != 0) &&
445 ((srf_rotate != driver_data->local_rotation) || (rotate_srf_rotate != driver_data->local_rotation))) {
446 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Use texstreaming due to different VA surface rotation and final rotaion\n",
447 srf_rotate, rotate_srf_rotate);
448 driver_data->output_method = PSB_PUTSURFACE_TEXSTREAMING;
449 return 0;
450 }
451
452 driver_data->output_method = PSB_PUTSURFACE_COVERLAY;
453
454 return 0;
455 }
456 #endif
457
psb_PutSurface(VADriverContextP ctx,VASurfaceID surface,void __maybe_unused * android_isurface,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)458 VAStatus psb_PutSurface(
459 VADriverContextP ctx,
460 VASurfaceID surface,
461 void __maybe_unused * android_isurface,
462 short srcx,
463 short srcy,
464 unsigned short srcw,
465 unsigned short srch,
466 short destx,
467 short desty,
468 unsigned short destw,
469 unsigned short desth,
470 VARectangle *cliprects, /* client supplied clip list */
471 unsigned int number_cliprects, /* number of clip rects in the clip list */
472 unsigned int flags /* de-interlacing flags */
473 )
474 {
475 INIT_DRIVER_DATA;
476 INIT_OUTPUT_PRIV;
477 object_surface_p obj_surface;
478 VAStatus vaStatus = VA_STATUS_SUCCESS;
479 PsbPortPrivPtr pPriv = (PsbPortPrivPtr)(&driver_data->coverlay_priv);
480 int ret = 0;
481
482 #ifndef BAYTRAIL
483
484 obj_surface = SURFACE(surface);
485
486 // psb__dump_NV_buffers(obj_surface,srcx,srcy,srcw,srch);
487 CHECK_SURFACE(obj_surface);
488 CHECK_INVALID_PARAM((NULL == cliprects) && (0 != number_cliprects));
489
490 if ((srcx < 0) || (srcx > obj_surface->width) || (srcw > (obj_surface->width - srcx)) ||
491 (srcy < 0) || (srcy > obj_surface->height_origin) || (srch > (obj_surface->height_origin - srcy))) {
492 drv_debug_msg(VIDEO_DEBUG_ERROR, "vaPutSurface: source rectangle passed from upper layer is not correct.\n");
493 return VA_STATUS_ERROR_UNKNOWN;
494 }
495 if ((destx < 0) || (desty < 0)) {
496 drv_debug_msg(VIDEO_DEBUG_ERROR, "vaPutSurface: dest rectangle passed from upper layer is not correct.\n");
497 return VA_STATUS_ERROR_UNKNOWN;
498 }
499
500 if (driver_data->dummy_putsurface) {
501 drv_debug_msg(VIDEO_DEBUG_GENERAL, "vaPutSurface: dummy mode, return directly\n");
502 return VA_STATUS_SUCCESS;
503 }
504
505 /* init overlay */
506 if (!driver_data->coverlay_init) {
507 ret = psb_coverlay_init(ctx);
508 if (ret != 0) {
509 drv_debug_msg(VIDEO_DEBUG_GENERAL, "vaPutSurface: psb_coverlay_init failed. Fallback to texture streaming.\n");
510 driver_data->coverlay_init = 0;
511 } else
512 driver_data->coverlay_init = 1;
513 }
514
515 /* set the current displaying video frame into kernel */
516 psb_surface_set_displaying(driver_data, obj_surface->width,
517 obj_surface->height_origin,
518 obj_surface->psb_surface);
519
520 /* local video playback */
521 drv_debug_msg(VIDEO_DEBUG_GENERAL, "MIPI: Use overlay to display.\n");
522
523 /*initialize output destbox using default destbox if it has not been initialized until here.*/
524 if (output->destw == 0 || output->desth == 0) {
525 output->destx = (destx > 0) ? destx : 0;
526 output->desty = (desty > 0) ? desty : 0;
527 output->destw = ((output->destx + destw) > output->screen_width) ? (output->screen_width - output->destx) : destw;
528 output->desth = ((output->desty + desth) > output->screen_height) ? (output->screen_height - output->desty) : desth;
529 }
530
531 drv_debug_msg(VIDEO_DEBUG_GENERAL, "Overlay position = (%d,%d,%d,%d)\n", output->destx, output->desty, output->destw, output->desth);
532 srcw = srcw <= 2047? srcw : 2047;
533 vaStatus = psb_putsurface_overlay(ctx, surface,
534 srcx, srcy, srcw, srch,
535 output->destx, output->desty, output->destw, output->desth,
536 flags, OVERLAY_A, PIPEA);
537
538 driver_data->frame_count++;
539 #endif
540 return vaStatus;
541 }
542