source: svn/newcon3bcm2_21bu/nexus/modules/display/7552/src/nexus_video_window.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 93.5 KB
Line 
1/***************************************************************************
2 *     (c)2007-2011 Broadcom Corporation
3 *
4 *  This program is the proprietary software of Broadcom Corporation and/or its licensors,
5 *  and may only be used, duplicated, modified or distributed pursuant to the terms and
6 *  conditions of a separate, written license agreement executed between you and Broadcom
7 *  (an "Authorized License").  Except as set forth in an Authorized License, Broadcom grants
8 *  no license (express or implied), right to use, or waiver of any kind with respect to the
9 *  Software, and Broadcom expressly reserves all rights in and to the Software and all
10 *  intellectual property rights therein.  IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU
11 *  HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY
12 *  NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE.
13 *
14 *  Except as expressly set forth in the Authorized License,
15 *
16 *  1.     This program, including its structure, sequence and organization, constitutes the valuable trade
17 *  secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof,
18 *  and to use this information only in connection with your use of Broadcom integrated circuit products.
19 *
20 *  2.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
21 *  AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
22 *  WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
23 *  THE SOFTWARE.  BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES
24 *  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE,
25 *  LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION
26 *  OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF
27 *  USE OR PERFORMANCE OF THE SOFTWARE.
28 *
29 *  3.     TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
30 *  LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR
31 *  EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR
32 *  USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF
33 *  THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT
34 *  ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE
35 *  LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF
36 *  ANY LIMITED REMEDY.
37 *
38 * $brcm_Workfile: nexus_video_window.c $
39 * $brcm_Revision: 184 $
40 * $brcm_Date: 12/21/11 12:47p $
41 *
42 * Module Description:
43 *
44 * Revision History:
45 *
46 * $brcm_Log: /nexus/modules/display/7400/src/nexus_video_window.c $
47 *
48 * 184   12/21/11 12:47p erickson
49 * SW7425-1971: call NEXUS_VideoInput_Shutdown when we call the last
50 *  NEXUS_VideoWindow_RemoveInput to clear the copy of the parent's
51 *  VDC_Source
52 *
53 * 183   11/15/11 3:27p erickson
54 * SW7425-1747: remove old code
55 *
56 * 182   10/20/11 5:12p erickson
57 * SW7420-1992: remove unnecessary priv function
58 *
59 * 181   10/20/11 1:43p erickson
60 * SW7420-1992: add private api's for atomically setting multiple video
61 *  window settings
62 *
63 * 180   9/8/11 1:06p erickson
64 * SW7425-1263: add
65 *  NEXUS_CalculateVideoWindowPositionSettings.displayAspectRatio
66 *
67 * 179   9/6/11 10:41a erickson
68 * SW7346-472: clean up 3D right-view buffer returned by
69 *  BVDC_Window_GetBuffer
70 *
71 * 178   9/2/11 12:40p erickson
72 * SW7420-1995: unregister handles from objdb when doing automatic close
73 *
74 * 177   8/8/11 5:22p mward
75 * SW7125-1065:  DEADCODE:  otherWindow used only #if
76 *  NEXUS_NUM_VIDEO_WINDOWS > 1.
77 *
78 * 176   7/26/11 3:04p randyjew
79 * SW7420-1959:Use NEXUS_NUM_MOSAIC_DECODES to prevent mosaic calls
80 *
81 * 175   7/18/11 2:01p akam
82 * SWDTV-7887: Fixed inaccurate window settings caused by rounding error.
83 *
84 * 174   7/15/11 11:16a jtna
85 * SW7420-1959: defensive programming if clearRect disabled
86 *
87 * 173   7/14/11 4:35p jtna
88 * SW7420-1959: added NEXUS_VideoWindowSettings.clearRect
89 *
90 * 172   7/12/11 11:03a erickson
91 * SW7420-1973: NEXUS_VideoWindow_SetSettings should fail on mosaic parent
92 *
93 * 171   7/7/11 10:57a erickson
94 * SW7405-5394: move BVDC_Window_SetMasterFrameRate logic into
95 *  NEXUS_VideoWindow_P_ConfigMasterFrameRate, which is called from all
96 *  places where it could change.
97 *
98 * 170   6/28/11 1:25p erickson
99 * SW7405-5366: protect against div-by-zero
100 *
101 * 169   6/28/11 9:48a erickson
102 * SW7405-5366: add NEXUS_VideoWindowStatus.phaseDelay
103 *
104 * 168   6/27/11 5:02p erickson
105 * SW7425-466: backout mosaic zorder workaround. problem solved in
106 *  nexus_display_mosaic.c instead.
107 *
108 * 167   5/26/11 1:42p erickson
109 * SW7425-645: update definition of scaleFactorRounding in
110 *  NEXUS_VideoWindowSettings
111 *
112 * 166   5/17/11 1:28p pntruong
113 * SW7425-527, SW7425-528: Select the heap index base on window's index
114 *  instead of z-order which is configurable by api.
115 *
116 * 165   5/13/11 9:51a erickson
117 * SW7425-525: add NEXUS_VideoWindowSettings.minimumDisplayFormat
118 *
119 * 164   4/22/11 3:13p vsilyaev
120 * SW7425-416: Updated 3D display API
121 *
122 * 163   4/20/11 6:11p jtna
123 * SW7425-365: fix build warnings for 2.6.37 kernel
124 *
125 * 162   4/19/11 1:54p erickson
126 * SW7405-5224: add NEXUS_VideoWindowSettings.preferSyncLock and
127 *  NEXUS_VideoWindowStatus.isSyncLocked
128 *
129 * 161   3/4/11 1:22p erickson
130 * SW7125-833: add NEXUS_VideoWindowContentMode_ePanScanWithoutCorrection
131 *
132 * 160   3/2/11 12:18p erickson
133 * SW7420-1560: change NEXUS_CalculateVideoWindowPosition (not backward
134 *  compatible) so that NEXUS_VideoWindowSettings param is not [in/out]
135 *
136 * 159   2/28/11 10:37a katrep
137 * SW7405-5146:compiler warning
138 *
139 * 158   2/28/11 9:29a katrep
140 * SW7405-5146:fixed compiler warning in DEBUG=n mode
141 *
142 * 157   12/28/10 3:57p erickson
143 * SW7405-5064: added NEXUS_VideoWindowStatus.outputRect and
144 *  NEXUS_VideoWindowSettings.outputRectChanged
145 *
146 * 156   12/2/10 3:55p erickson
147 * SW7420-1227: rework
148 *  NEXUS_GetDefaultCalculateVideoWindowPositionSettings
149 *
150 * 155   11/29/10 1:58p erickson
151 * SW7405-715: remove PR 42625 bandwidth restriction. it is not general.
152 *  it only applies to some chips with some RTS settings. this should not
153 *  be in general purpose code.
154 *
155 * 154   11/18/10 7:27p spothana
156 *  SW7420-1078: Assign heap index per video window and per graphics
157 *  buffer.
158 *
159 * SW7420-1078/2   11/15/10 11:16a spothana
160 * SW7420-1078: Correct the assignment for the window heaps.
161 *
162 * SW7420-1078/1   11/11/10 6:26p spothana
163 * SW7420-1078: Assign heap index per video window and per graphics
164 *  buffer.
165 *
166 * 153   11/1/10 10:59a erickson
167 * SW7422-43: adapt to BVDC_Window_ReturnBuffer changes
168 *
169 * 152   10/19/10 5:39p nickh
170 * SW7422-10: Allocate the PIP on the main display from MEMC0
171 *
172 * 151   10/18/10 5:23p petlee
173 * SW35230-990: Add flag to indicate where histogram is performed
174 *
175 * 150   10/14/10 5:08p erickson
176 * SW7420-565: init dcTable2
177 *
178 * 149   10/12/10 10:43a spothana
179 *  SW7420-1157 : Match the VDC memory usage in the reference software to
180 *  memory worksheet
181 *
182 * 148   9/10/10 4:35p erickson
183 * SW7550-556: added NEXUS_VideoWindowSettings.scaleFactorRounding for
184 *  manual control. default to automatic control.
185 *
186 * 147   8/3/10 5:11p spothana
187 * SW7420-732: By default set the DNR/ANR blocks in bypass state rather
188 *  than in disable. Toggling between disable and enable states results in
189 *  flashing of video.
190 *
191 * 146   7/6/10 2:03p petlee
192 * SW35230-484: Add FRC split screen mode
193 *
194 * 145   6/1/10 9:39p bandrews
195 * SW3548-2323: unlinked work on 7420 with 35230, input and display only
196 *  tuned on latter
197 *
198 * 144   5/13/10 2:06p erickson
199 * SW7405-4239: with VDC algorithm improvements, first param to
200 *  BVDC_Window_SetScaleFactorRounding should be zero in all cases
201 *
202 * 143   5/5/10 7:26p bandrews
203 * SW3548-2323: updated to use apply changes if update mode says so
204 *
205 * 142   4/6/10 8:02p bandrews
206 * SW7405-4147,SW7468-176,SW7208-12: fix initial call to sync channel so
207 *  that it communicates delay, not zero
208 *
209 * 141   4/1/10 2:59p erickson
210 * SW7405-4074: set windowCfg.bDeinterlacerAllocFull so that
211 *  NEXUS_VideoWindowGameMode is easier to use across different chips
212 *
213 * 140   3/30/10 6:39p bandrews
214 * SW3548-2323: proxy code generator doesn't like arrays as parameters to
215 *  public APIs
216 *
217 * 139   3/30/10 4:49p bandrews
218 * SW3548-2323: merge to main, need to match header
219 *
220 * 138   3/29/10 3:41p bandrews
221 * SW3548-2323: merge to main
222 *
223 * SW3548-2323/7   3/8/10 8:59p bandrews
224 * SW3548-2323: merge from latest
225 *
226 * 137   3/26/10 2:19p erickson
227 * SW7405-3965: refactor mosaic to support hd/sd simul mode
228 *
229 * 136   3/23/10 11:14a erickson
230 * SW7550-325: fix non-linear A/R when transition to/from fullscreen
231 *
232 * 135   3/3/10 3:00p nickh
233 * SW7420-565: Write default dynamic contrast tables
234 *
235 * 134   2/19/10 3:30p erickson
236 * SW7405-3625: fix non-mosaic capable systems
237 *
238 * 133   2/19/10 1:23p erickson
239 * SW7405-3625: add NEXUS_VideoWindowMosaicSettings for backendMosaic
240 *  support
241 *
242 * 132   2/17/10 1:30p erickson
243 * SW3548-2776: fix settop
244 *
245 * 131   2/16/10 4:47p erickson
246 * SW3548-2776: add
247 *  NEXUS_PictureCtrlContrastStretch.dynamicBacklightScaleFactor
248 *
249 * 130   2/11/10 1:30p erickson
250 * SW7405-3829: change impl to new vdc bShrinkWidth api
251 *
252 * 129   2/10/10 2:35p erickson
253 * SW7405-3829: refactor internal functions to create/destroy VDC window.
254 *  NEXUS_VideoWindowMadSettings.shrinkWidth requires window to be
255 *  recreated.
256 *
257 * 128   2/3/10 12:26p erickson
258 * SW3548-2727: add NEXUS_VideoWindowSettings.sourceClip
259 *
260 * BCM3D/3   1/29/10 11:16a erickson
261 * SW3548-2727: add NEXUS_VideoWindowSettings.sourceClip
262 *
263 * 127   2/1/10 7:07p bandrews
264 * SW7405-3783: need to notify sync channel of vdc delay on connect,
265 *  otherwise it won't ever get the delay
266 *
267 * SW3548-2323/6   2/1/10 7:04p bandrews
268 * SW7405-3783: need to notify sync channel on connect of window delay
269 *
270 * SW3548-2323/5   1/26/10 4:00p bandrews
271 * SW3548-2323: merge from main
272 *
273 * 126   1/21/10 3:58p erickson
274 * SW7405-3783: NEXUS_VideoWindowStatus.delay should be set even if
275 *  SyncChannel is not used
276 *
277 * 125   1/18/10 4:55p petlee
278 * SW35230-60: Temporary fix to make Nexus Display build for 35230; Remove
279 *  this fix once DTV-VDC team completes port of SW7405-3718.
280 *
281 * 124   1/11/10 2:02p erickson
282 * SW7405-3718: add NEXUS_VideoWindowAfdSettings
283 *
284 * 123   1/6/10 4:18p erickson
285 * SW7405-3533: move window init code into NEXUS_VideoWindow_P_InitState.
286 *  this allows normal and mosaic windows to init to the same defaults.
287 *
288 * SW3548_2323/4   12/15/09 8:50p bandrews
289 * SW3548-2323: updated from VDC team's vdc_tune impl
290 *
291 * SW3548_2323/3   12/15/09 8:36p bandrews
292 * SW3548-2323: merge from latest
293 *
294 * 122   12/9/09 5:00p erickson
295 * SW7405-3394: fix non-mosaic
296 *
297 * 121   12/9/09 3:10p erickson
298 * SW7405-3394: refactor mosaic mode API
299 *
300 * 120   12/3/09 12:08p erickson
301 * SW3548-2619: fix warning
302 *
303 * 119   12/3/09 11:20a erickson
304 * SW3548-2619: added NEXUS_VideoWindowSettings.minimumSourceFormat
305 *
306 * 118   11/19/09 3:48p erickson
307 * SW3556-847: increasing delay in NEXUS_VideoWindow_CaptureVideoBuffer
308 *
309 * 117   11/10/09 5:07p mward
310 * SW7400-2574: Only set split screen mode on first window of primary
311 *  display also applies to 7400 for most settings.
312 *
313 * 116   11/10/09 2:16p nickh
314 * SW7420-166:  Add support for 3rd display and DUAL_OUTPUT
315 *
316 * 115   11/10/09 2:39p gkamosa
317 * SW3548-2609: Update NEXUS_CalculateVideoWindowPosition to detect cases
318 *  where eZoom or eBox AR correction is requested and the source and
319 *  display AR are the same.  In these cases, avoid un-necessary
320 *  calculations on viewport or clipping as fixed point inaccuracies may
321 *  cause the coordinates calculated to be out of bounds, leading to an
322 *  unnecessary API failure.
323 *
324 * 114   11/3/09 5:23p mphillip
325 * SW7405-3342: Remove assertion now that NULL settings are allowed
326 *
327 * 113   11/2/09 10:43a erickson
328 * SW3548-2584: allow NULL color matrix for
329 *  NEXUS_VideoWindow_SetColorMatrix
330 *
331 * 112   10/27/09 6:53p mward
332 * SW7125-45: Only set split screen mode on first window of primary
333 *  display.
334 *
335 * 111   10/27/09 10:54a erickson
336 * SW3548-2577: remove bSmoothScaling. NEXUS_ScalerCaptureBias is
337 *  equivalent.
338 *
339 * 110   10/15/09 4:31p erickson
340 * SWDEPRECATED-3881: don't use deprecated struct members. use NEXUS_NUM
341 *  defines
342 *
343 * 109   10/7/09 3:35p erickson
344 * SW7405-3140: fix NEXUS_VideoWindowContentMode_ePanScan
345 *
346 * 108   10/5/09 1:10p erickson
347 * SW3548-2527: use colorMatrixAOverride (and B/C) in
348 *  NEXUS_VideoWindow_P_SetVdcSettings
349 *
350 * SW3548_2323/2   9/28/09 8:23p bandrews
351 * 3548-2323: initial check-in of libtune port
352 *
353 * SW3548_2323/1   9/22/09 6:50p bandrews
354 * SW3548-2323: libTune nexus passthrough
355 *
356 * 107   9/22/09 11:16a erickson
357 * SW3548-2487: need to check layout when user changes contentMode
358 *
359 * 106   9/17/09 3:02p erickson
360 * SW3548-2348: account for window heaps separately from input heaps
361 *
362 * 105   9/14/09 12:56p erickson
363 * SW3548-2374: add more sourceAspectRatio support including eSar and
364 *  eSquarePixel
365 *
366 * 104   8/26/09 5:58a erickson
367 * SW3548-2374: fix negative x/y coordinates in
368 *  NEXUS_CalculateVideoWindowPositionSettings.viewport
369 *
370 * 103   8/26/09 5:18a erickson
371 * SW3548-2374: added NEXUS_CalculateVideoWindowPosition
372 *
373 * 102   8/19/09 11:02a erickson
374 * PR57098: added NEXUS_VideoWindowSettings.delay
375 *
376 * 101   8/19/09 10:24a erickson
377 * PR57747: add BDBG_ERR if window position/clipRect/clipBase are bad
378 *
379 * 100   8/10/09 10:09a erickson
380 * PR56325: only feedback display information to sync-locked inputs
381 *
382 * 99   8/10/09 8:17a gmohile
383 * PR 56400 : Merge legacy vdc support to main line
384 *
385 * 98   7/31/09 11:17a gmohile
386 * PR 56512 : Add 7403 support
387 *
388 * 97   7/30/09 5:17p erickson
389 * PR57216: added dejagging and deringing to
390 *  NEXUS_VideoWindowSplitScreenSettings
391 *
392 * 96   7/23/09 4:24p jrubio
393 * PR56975: make sure DNR_DEMO_MODE is not turned off when another
394 *  Display/Window has it turned on
395 *
396 * 95   7/20/09 9:16a erickson
397 * PR55237: added NEXUS_VideoWindowSettings.allocateFullScreen
398 *
399 * 94   6/12/09 10:50a erickson
400 * PR55967: convert NEXUS_DisplayModuleSettings heap settings to integers.
401 *  This makes them settable in the application.
402 *
403 * 93   5/20/09 3:29p erickson
404 * PR54880: keep track of whether VDC heaps were created and only destroy
405 *  what was created
406 *
407 * 92   5/19/09 10:59a erickson
408 * PR54880: fix heap handling. don't assume VideoDecoder will return NULL
409 *  heap for default.
410 *
411 * 91   4/23/09 11:28a jgarrett
412 * PR 54424: Fixing continuous VDB prints related to content mode
413 *  correction
414 *
415 * 90   4/20/09 4:37p jgarrett
416 * PR 54346: Changing ForceZoom to ForceFull, adding better recovery from
417 *  invalid app states.
418 *
419 * 89   4/15/09 11:00a jgarrett
420 * PR 51743: Fixing default forceBox state
421 *
422 * 88   4/14/09 4:50p jgarrett
423 * PR 51743: Updating BVDB_GetVideoDisplayMode to new args
424 *
425 * 87   4/9/09 5:21p katrep
426 * PR52197: For panscan vdc aspect ratio should be set to all source.
427 *
428 * 86   4/9/09 2:20p erickson
429 * PR53838: fix settop
430 *
431 * 85   4/9/09 10:43a erickson
432 * PR53838: use VDB's maxFormat if specialFeature1 enabled
433 *
434 * 84   3/30/09 2:27p erickson
435 * PR52520: downgrade WRN to MSG
436 *
437 * 83   3/27/09 10:31a erickson
438 * PR48963: add heap and pipHeap to NEXUS_DisplayModuleSettings. allows
439 *  for more platform configurability.
440 *
441 * 82   3/18/09 10:43a erickson
442 * PR52461: set BVDC_Window_SplitScreenSettings.eAnr for all chips
443 *
444 * 81   3/17/09 3:42p erickson
445 * PR52461: removing vdc source anr setting
446 *
447 * 80   3/10/09 4:30p erickson
448 * PR53042: check for NULL on every call to NEXUS_VideoInput_P_Get
449 *
450 * 79   3/6/09 7:49p jgarrett
451 * PR 52849: Fixing pixel limitations
452 *
453 * 78   3/2/09 6:10p jgarrett
454 * PR 52520: Moving scaler settings to common functions for VDB support
455 *
456 * 77   2/26/09 2:32p jgarrett
457 * PR 52166: Following VDB forcePending directly, no app settings allowed
458 *
459 * 76   2/24/09 6:24p nickh
460 * PR52461: Merge 7420 ANR Nexus changes to main branch
461 *
462 * 7420_mcvp/3   2/24/09 6:20p nickh
463 * PR52461: Restrict ANR changes to 7420
464 *
465 * 7420_mcvp/2   2/13/09 6:01p tdo
466 * PR 45785, PR 45789: merge from main branch on 2/13/09
467 *
468 * 7420_mcvp/1   2/5/09 9:51a syang
469 * PR 45785, PR 45789:  get rid of BVDC_Source_Get/SetAnrConfiguration
470 *
471 * 75   2/12/09 11:23p erickson
472 * PR51976: fix NEXUS_VideoWindowSettings.autoMaster logic
473 *
474 * 74   1/6/09 11:33a jgarrett
475 * PR 48984: Merge dynamic RTS code to main branch
476 *
477 * PR48984/4   12/10/08 11:29a jgarrett
478 * PR 48984: Saving window settings immediately for VDB.
479 *
480 * PR48984/3   12/5/08 4:23p jgarrett
481 * PR 48984: Updating to latest baseline
482 *
483 * 73   11/26/08 2:15p erickson
484 * PR49203: allow unguarded BVDC_ApplyChanges for
485 *  NEXUS_VideoWindow_SetSyncSettings_priv
486 *
487 * PR48984/2   11/26/08 6:19p jgarrett
488 * PR 48984: Merging to latest baseline
489 *
490 * 72   11/25/08 11:26a mward
491 * PR47739:  Display/Compositor 2 has only one video window.
492 *
493 * PR48984/1   11/20/08 6:47p jgarrett
494 * PR 48984: Adding vdb restrictions
495 *
496 * 71   11/17/08 12:28p erickson
497 * PR49203: ensure there are no unnecessary unguarded BVDC_ApplyChanges
498 *  calls in Nexus
499 *
500 * 70   11/4/08 12:38p erickson
501 * PR47030: add NEXUS_Display_P_DestroyHeap, refactor so that all VDC
502 *  Sources are created by NEXUS_VideoInput_P_CreateLink
503 *
504 * 69   10/30/08 8:55p erickson
505 * PR47030: use heap handle
506 *
507 * 68   10/20/08 6:55p bandrews
508 * PR46915: Don't assert on NULL vdc window handle
509 *
510 * 67   10/7/08 10:00p erickson
511 * PR47583: added ApplyChanges after BVDC_Window_ReturnBuffer
512 *
513 * 66   10/6/08 10:51p erickson
514 * PR47583: free up memory from inside VDC for
515 *  NEXUS_VideoWindow_CaptureVideoBuffer
516 *
517 * 65   10/6/08 10:21p erickson
518 * PR40799: fix link->ref_cnt
519 *
520 * 64   10/5/08 8:26p erickson
521 * PR47583: debug cleanup
522 *
523 * 63   10/2/08 12:54p erickson
524 * PR40799: reorder calls in NEXUS_VideoWindow_AddInput to allow input to
525 *  create/destroy BVDC_Source when connected/disconnected
526 *
527 * 62   9/22/08 9:54a erickson
528 * PR46063: support getting format info re: Custom2 inside and outside
529 *  nexus
530 *
531 * 61   9/17/08 12:29p erickson
532 * PR47014: expose compositor blend equation in NEXUS_VideoWindowSettings
533 *  and NEXUS_GraphicsSettings
534 *
535 * 60   9/12/08 1:28p erickson
536 * PR46813: fix check for window
537 *
538 * 59   9/8/08 11:40a erickson
539 * PR35457: remove bad comment
540 *
541 * 58   9/3/08 1:33p erickson
542 * PR46254: added NEXUS_VideoWindowSettings.alpha
543 *
544 * 57   9/2/08 7:48p katrep
545 * PR46457: Configure nexus features at the run time based on board strap
546 *  options
547 *
548 * 56   8/14/08 5:26p katrep
549 * PR45674: Fix compiiler warning in kernel mode non debug builds
550 *
551 * 55   7/25/08 12:39p erickson
552 * PR42625: prevent BVN bandwidth problem when using
553 *  BVDC_AspectRatioMode_eUseAllDestination
554 *
555 * 54   7/3/08 5:08p erickson
556 * PR43699: Remove unnecessary VDC Get functions from Nexus to avoid race
557 *  conditions
558 *
559 * 53   7/3/08 4:21p erickson
560 * PR44452: closing a window should automatically remove its inputs
561 *
562 * 52   6/25/08 1:03p erickson
563 * PR43785: set BVDC_Window_SetScaleFactorRounding to 0,0 for CRC test
564 *
565 * 51   6/20/08 9:33a erickson
566 * PR43917: defautl bSmoothScaling = false for DTV
567 *
568 * 50   6/19/08 2:18p bandrews
569 * PR42268: Tell sync properly about master frame rate
570 *
571 * 49   6/17/08 4:21p vsilyaev
572 * PR 43102: Fixed warning
573 *
574 * 48   6/16/08 9:18a erickson
575 * PR43102: merge
576 *
577 * PR43102/1   5/30/08 6:26p gorgon
578 * PR43102: PC auto position failed in 1280x1024 with astro.
579 *
580 * 47   6/13/08 12:34p erickson
581 * PR42625: backing out fix for now
582 *
583 * 46   5/29/08 1:22p erickson
584 * PR43126: defer BVDC_ApplyChanges in PQ code while resetting all VDC
585 *  settings for a window.
586 *
587 * 45   5/23/08 11:50a erickson
588 * PR42998: add NEXUS_VideoWindowSettings.letterBoxAutoCut
589 *
590 * 44   5/23/08 10:49a erickson
591 * PR42982: rework PQ Dirty logic to reapply settings on channel change
592 *
593 * 43   5/22/08 11:07a erickson
594 * PR42625: hardcode BVDC_Window_Settings.bSmoothScaling to false to avoid
595 *  BVN bandwidth problems
596 *
597 * 42   5/22/08 11:04a erickson
598 * PR42625: remove B_HAS_LEGACY_VDC code in preperation for fix
599 *
600 * 41   5/9/08 12:44p erickson
601 * PR39453: add sourcePending callback, set status.sourcePending based on
602 *  VDC dirty bits.
603 *
604 * 40   5/6/08 9:51a erickson
605 * PR42214: DTV wants BVDC_Window_SetScaleFactorRounding(0,0)
606 *
607 * 39   5/5/08 4:48p erickson
608 * PR42445: provide API's for better display frame rate control
609 *
610 * 38   5/1/08 12:57p erickson
611 * PR41202: add NEXUS_VideoWindowSettings.forceCapture
612 *
613 * 37   5/1/08 12:12p erickson
614 * PR41202: merge
615 *
616 * 36   4/30/08 4:42p erickson
617 * PR39453: add 3548/3556 impl
618 *
619 * 35   4/30/08 3:08p erickson
620 * PR39453: add 3548/3556 features
621 *
622 * 34   4/24/08 11:07a erickson
623 * PR42071: fix NEXUS_VideoWindow_AddInput and allow for future multi-
624 *  module connections
625 *
626 * 33   4/24/08 10:51a erickson
627 * PR42071: only call NEXUS_VideoInput_P_Connect if refcnt == 0
628 *
629 * 32   4/23/08 4:30p erickson
630 * PR42071: fix NEXUS_VideoWindow_P_Teardown
631 *
632 * 31   4/14/08 9:17a erickson
633 * PR39003: move PQ functions below SetZorder for PIP systems
634 *
635 * 30   4/4/08 10:43a erickson
636 * PR41063: opened backdoor to BVDC_Window_SetScalerOutput. if clipBase
637 *  width & height are 0, we pass clipRect directly into
638 *  BVDC_Window_SetScalerOutput. usage needs to be documented in interface
639 *  after it is clarified.
640 *
641 * 29   4/3/08 1:30p erickson
642 * PR40567: merge
643 *
644 * PR40567/3   4/3/08 5:39p dyzhang
645 * PR40567: need to translate to magnum pixel form from nexus one
646 *
647 * PR40567/2   4/3/08 5:35p dyzhang
648 * PR40567: merge from the mainline
649 *
650 * 27   4/2/08 11:31a erickson
651 * PR40198: fix DEBUG=n warning
652 *
653 * 26   4/2/08 9:16a erickson
654 * PR40567: merge
655 *
656 * PR40567/1   4/2/08 10:35a dyzhang
657 * PR40567: add capture/feeder pixel format control
658 *
659 * 25   4/1/08 3:32p vsilyaev
660 * PR 41027: Added use fixed mapping between nexus and VDC windowId's
661 *
662 * 24   4/1/08 3:19p vsilyaev
663 * PR 41027: Added use fixed mapping between nexus and VDC windowId's
664 *
665 * 23   4/1/08 1:34p erickson
666 * PR40411: merge. added lb_event to drive pcinput position algo.
667 *
668 * 40411_take2/1   4/1/08 6:31p gorgon
669 * PR40411: add letterBoxDetectionChange and GetLetterBoxStatus. Use event
670 *  to triger lb.
671 *
672 * 22   3/27/08 6:20p vsilyaev
673 * PR 40818: Added management of VDC heaps
674 *
675 * 21   3/26/08 3:38p vsilyaev
676 * PR 40862: Added code to propagate display framerate to the decoder
677 *
678 * 20   3/20/08 3:00p erickson
679 * PR40411: add letterBoxDetectionChange and GetLetterBoxStatus
680 *
681 * 19   3/11/08 2:10p erickson
682 * PR40222: add NEXUS_VideoWindow_GetStatus to report video delay
683 *
684 * 18   3/3/08 10:34a erickson
685 * PR40156: don't apply a window color matrix unless Set
686 *
687 * 17   3/3/08 9:21a erickson
688 * PR40156: fix legacy VDC
689 *
690 * 16   2/29/08 5:39p erickson
691 * PR40156: implement ColorMatrix function
692 *
693 * 15   2/28/08 8:54p bandrews
694 * PR37951: Synclib must use stream progressive, not frame progressive.
695 *  Master frame rate status needs to be updated before handing to sync.
696 *
697 * 14   2/26/08 6:48p bandrews
698 * PR37951: Fixed frame rate conversion to BAVC enum
699 *
700 * 13   2/25/08 9:34p bandrews
701 * PR37951: Apply changes must be called in order to install the callback
702 *
703 * 12   2/21/08 5:48p erickson
704 * PR39003: PQ api change
705 *
706 * 11   2/20/08 11:56a erickson
707 * PR39003: all !LEGACY chips now have VDC api changes
708 *
709 * 10   2/7/08 2:50p erickson
710 * PR39003: added #if BCHP_CHIP and comment for VDC api changes
711 *
712 * 9   2/6/08 4:27p vsilyaev
713 * PR 38682: Corrected logic for the 'window->open' flag
714 *
715 * 8   2/4/08 9:50a erickson
716 * PR39003: update code for legacy VDC
717 *
718 * 7   2/4/08 9:34a erickson
719 * PR38679: remove test for input->destination
720 *
721 * 6   1/31/08 9:55a erickson
722 * PR36808: added SyncChannel interface
723 *
724 * 5   1/25/08 10:10a erickson
725 * PR39003: fix 740x which doesn't have recent VDC change
726 *
727 * 4   1/25/08 9:42a erickson
728 * PR39003: adapt to latest VDC
729 *
730 * 3   1/23/08 9:22p vobadm
731 * PR35457: update docs
732 *
733 * 2   1/23/08 12:39p erickson
734 * PR38919: rename NEXUS_Display_GetWindow to NEXUS_VideoWindow_Open
735 *
736 * 1   1/18/08 2:20p jgarrett
737 * PR 38808: Merging to main branch
738 *
739 * Nexus_Devel/4   1/9/08 12:14p vsilyaev
740 * PR 34662: Implemented VideoInput_GetStatus for legacy VDC
741 *
742 * Nexus_Devel/3   1/8/08 5:32p erickson
743 * PR36159: fix 7401
744 *
745 * Nexus_Devel/2   1/8/08 10:57a erickson
746 * PR36159: refactor some 3563 Display API's
747 *
748 * Nexus_Devel/1   1/3/08 8:43p erickson
749 * PR34662: refactor into smaller files
750 *
751 ***************************************************************************/
752#include "nexus_display_module.h"
753#include "priv/nexus_surface_priv.h"
754#include "nexus_class_verification.h"
755
756BDBG_MODULE(nexus_video_window);
757
758BDBG_OBJECT_ID(NEXUS_VideoWindow);
759
760#define BDBG_MSG_TRACE(X)
761
762static const uint32_t aIreTable[NEXUS_DC_TABLE_COLS - 1] =  {
763     64, 100, 152, 239, 327, 414, 502, 590, 677, 765, 852, 940, 956, 972, 988, 1004
764};
765
766
767static const uint32_t alDCTable1[NEXUS_DC_TABLE_ROWS * NEXUS_DC_TABLE_COLS] = {
768    /* Used for settop-box */
769     64, 64, 100, 190, 382, 550, 658, 735, 799, 826, 874, 916, 940, 940, 940, 940, 940,
770     75, 64, 100, 190, 382, 550, 658, 735, 799, 826, 874, 916, 940, 940, 940, 940, 940,
771    124, 64,  99, 170, 310, 442, 560, 650, 722, 790, 840, 890, 940, 940, 940, 940, 940,
772    198, 64,  97, 160, 260, 406, 511, 601, 680, 753, 820, 880, 940, 940, 940, 940, 940,
773    275, 64,  94, 150, 235, 360, 460, 560, 650, 735, 815, 880, 940, 940, 940, 940, 940,
774    349, 64,  90, 140, 215, 328, 430, 531, 629, 725, 800, 870, 940, 940, 940, 940, 940,
775    425, 64,  85, 130, 200, 305, 418, 515, 624, 718, 795, 870, 940, 940, 940, 940, 940,
776    497, 64,  80, 120, 200, 292, 409, 508, 619, 711, 790, 866, 940, 940, 940, 940, 940,
777    572, 64,  80, 120, 200, 290, 395, 491, 602, 700, 783, 863, 940, 940, 940, 940, 940,
778    652, 64,  80, 120, 200, 290, 388, 481, 581, 684, 773, 860, 940, 940, 940, 940, 940,
779    723, 64,  80, 120, 200, 288, 384, 473, 569, 676, 768, 856, 940, 940, 940, 940, 940,
780    799, 64,  80, 120, 200, 282, 378, 469, 563, 661, 743, 840, 940, 940, 940, 940, 940,
781    875, 64,  80, 120, 200, 277, 375, 465, 558, 659, 742, 835, 940, 940, 940, 940, 940,
782    924, 64,  80, 120, 200, 275, 372, 463, 555, 650, 742, 834, 940, 940, 940, 940, 940,
783    940, 64,  80, 120, 200, 275, 372, 463, 555, 650, 742, 834, 940, 940, 940, 940, 940
784};
785
786#define pVideo (&g_NEXUS_DisplayModule_State)
787static NEXUS_Error NEXUS_VideoWindow_P_ApplySplitScreenSettings(NEXUS_VideoWindowHandle window);
788
789static void
790NEXUS_VideoWindow_P_LboxCallbackFunc_isr(void *pvParm1, int iParm2, const BVDC_BoxDetectInfo *pBoxDetectInfo)
791{
792    NEXUS_VideoWindowHandle window = pvParm1;
793    bool setevent = false;
794    uint32_t  ulOverflowHeight=0;
795
796    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
797    BSTD_UNUSED(iParm2);
798
799    /* for now, magnum maps straight to nexus. */
800    BDBG_CASSERT(sizeof(*pBoxDetectInfo) == sizeof(window->letterBoxStatus));
801
802    /* Set event for pc auto position if result changed */
803    if ((window->letterBoxStatus.whiteBoxLeft  != pBoxDetectInfo->ulWhiteBoxLeft  )||
804        (window->letterBoxStatus.whiteBoxTop   != pBoxDetectInfo->ulWhiteBoxTop   )||
805        (window->letterBoxStatus.whiteBoxWidth != pBoxDetectInfo->ulWhiteBoxWidth )||
806        (window->letterBoxStatus.whiteBoxHeight!= pBoxDetectInfo->ulWhiteBoxHeight))
807    {
808        /* don't set event until after memcpy */
809        /* LB only have 10 bits to indicate the height.*/
810        if((int32_t)(pBoxDetectInfo->ulWhiteBoxHeight) < 177)
811        {
812            ulOverflowHeight = 1024 + (int32_t)(pBoxDetectInfo->ulWhiteBoxHeight);
813        }
814        else
815        {
816            ulOverflowHeight = pBoxDetectInfo->ulWhiteBoxHeight;
817        }
818        if((pBoxDetectInfo->ulWhiteBoxWidth <= 1920) &&
819            (ulOverflowHeight <= 1200))
820        {
821            setevent = true;
822        }
823    }
824
825    BKNI_Memcpy(&window->letterBoxStatus, pBoxDetectInfo, sizeof(*pBoxDetectInfo));
826    NEXUS_IsrCallback_Fire_isr(window->letterBoxDetectionCallback);
827    if (setevent) {
828        window->letterBoxStatus.whiteBoxHeight = ulOverflowHeight;
829        BKNI_SetEvent(window->lb_event);
830    }
831}
832
833static BERR_Code NEXUS_VideoWindow_P_RecreateWindow(NEXUS_VideoWindowHandle window)
834{
835    BERR_Code rc;
836    NEXUS_VideoWindow_P_DestroyVdcWindow(window);
837    rc = NEXUS_VideoWindow_P_CreateVdcWindow(window, &window->cfg);
838    if (rc) return BERR_TRACE(rc);
839    rc = NEXUS_VideoWindow_P_SetVdcSettings(window, &window->cfg, true);
840    if (rc) return BERR_TRACE(rc);
841    return 0;
842}
843
844#define IS_DIGITAL_SOURCE(window) ((window)->input && (window)->input->type == NEXUS_VideoInputType_eDecoder)
845
846static BERR_Code NEXUS_VideoWindow_P_TestSyncLock(NEXUS_VideoWindowHandle window)
847{
848    unsigned j;
849    NEXUS_VideoWindowStatus status;
850    BERR_Code rc;
851
852    rc = NEXUS_VideoWindow_GetStatus(window, &status);
853    if (rc) return BERR_TRACE(rc);
854    if (status.isSyncLocked) return 0;
855
856    if (!IS_DIGITAL_SOURCE(window)) {
857        BDBG_ERR(("preferSyncLock only applies to digital sources"));
858        return BERR_TRACE(NEXUS_NOT_SUPPORTED);
859    }
860
861    /* if there's another digital window on this display, destroy & recreate it. then this window will become sync-locked. */
862    /* if there's another digital window for this source on another display, destroy & recreate it. then this window will become sync-locked. */
863    for (j=0;j<NEXUS_NUM_DISPLAYS;j++) {
864        unsigned i;
865        NEXUS_DisplayHandle d = pVideo->displays[j];
866        if (!d) continue;
867        for (i=0;i<NEXUS_NUM_VIDEO_WINDOWS;i++) {
868            NEXUS_VideoWindowHandle w = &d->windows[i];
869            if (!w->open || w == window) continue; /* skip closed or same window */
870
871            /* if the other window shares the same source or
872            another digital source on the same display, then it contends for sync lock. */
873            if (w->input == window->input || (d == window->display && IS_DIGITAL_SOURCE(w))) {
874                if (w->cfg.preferSyncLock) {
875                    BDBG_WRN(("two windows have preferSyncLock = true"));
876                    break;
877                }
878                else {
879                    NEXUS_VideoWindow_P_RecreateWindow(w);
880                }
881                break;
882            }
883        }
884    }
885    return 0;
886}
887
888BERR_Code
889NEXUS_VideoWindow_P_SetVdcSettings(NEXUS_VideoWindowHandle window, const NEXUS_VideoWindowSettings *settings, bool force)
890{
891    BERR_Code rc;
892    BVDC_Window_Handle windowVdc = window->vdcState.window;
893    bool callSync = false;
894    NEXUS_DisplayUpdateMode saveUpdateMode;
895#ifdef B_HAS_LEGACY_VDC
896#define BVDC_WindowId_eVideo0 0
897#define BVDC_WindowId_eVideo1 1
898#endif
899    bool isFullScreen;
900
901    /* first, see if we have to destroy and recreate windows for synclock preferences */
902    if (settings->preferSyncLock) {
903        NEXUS_VideoWindow_P_TestSyncLock(window);
904    }
905
906    /* We've about to make a lot of VDC changes. We do not want ApplyChanges called. This will temporarily mask it.
907    Be sure to restore it at the end, even in a failure case. */
908    saveUpdateMode = g_NEXUS_DisplayModule_State.updateMode;
909    g_NEXUS_DisplayModule_State.updateMode = NEXUS_DisplayUpdateMode_eManual;
910
911    BDBG_ASSERT(window->vdcState.window);
912
913    force = force || pVideo->lastUpdateFailed;
914
915    if(force || settings->autoMaster != window->cfg.autoMaster) {
916        rc = NEXUS_VideoWindow_P_ConfigMasterFrameRate(window, &window->display->cfg, settings);
917        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_windowCfg;}
918    }
919
920    #if NEXUS_HAS_DYNAMIC_RTS
921    /* The user setting for force capture has no effect on systems with dynamic RTS.  VDB gives us this info. */
922    if(force || window->restrictions.forceCapture != window->syncStatus.forcedCaptureEnabled)
923    {
924        rc = BVDC_Window_SetForceCapture(windowVdc, window->restrictions.forceCapture);
925        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_windowCfg;}
926        window->syncStatus.forcedCaptureEnabled = window->restrictions.forceCapture;
927    }
928    #else
929    if(force || settings->forceCapture != window->cfg.forceCapture ||
930       settings->forceCapture != window->syncStatus.forcedCaptureEnabled)
931    {
932        /* Be aware that SyncChannel requires force capture for smooth transitions. */
933        rc = BVDC_Window_SetForceCapture(windowVdc, settings->forceCapture);
934        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_windowCfg;}
935        window->syncStatus.forcedCaptureEnabled = settings->forceCapture;
936    }
937    #endif
938
939    if(force || settings->pixelFormat != window->cfg.pixelFormat || settings->pixelFormat != window->pixelFormat ||
940       !NEXUS_Vdb_P_PixelFormatValid(window->pixelFormat, window->restrictions.maxFormat))
941    {
942        BPXL_Format pixelFormat;
943        if (settings->pixelFormat != NEXUS_PixelFormat_eUnknown) {
944            NEXUS_PixelFormat nexusFormat = settings->pixelFormat;
945
946            if ( !NEXUS_Vdb_P_PixelFormatValid(settings->pixelFormat, window->restrictions.maxFormat) )
947            {
948                BDBG_WRN(("Window pixel format is not supported in the current usage mode.  Reducing window pixel format: %d -> %d.",
949                    settings->pixelFormat, window->restrictions.maxFormat));
950                nexusFormat = window->restrictions.maxFormat;
951            }
952
953            rc = NEXUS_P_PixelFormat_ToMagnum(nexusFormat, &pixelFormat);
954            if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc);goto err_windowCfg;}
955
956            rc = BVDC_Window_SetPixelFormat(windowVdc, pixelFormat);
957            if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowCfg;}
958            window->pixelFormat = nexusFormat;
959        }
960        else if ( window->restrictions.maxFormat != NEXUS_PixelFormat_eUnknown )
961        {
962            rc = NEXUS_P_PixelFormat_ToMagnum(window->restrictions.maxFormat, &pixelFormat);
963            if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowCfg;}
964
965            rc = BVDC_Window_SetPixelFormat(windowVdc, pixelFormat);
966            if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowCfg;}
967            window->pixelFormat = window->restrictions.maxFormat;
968        }
969    }
970
971    if(force || settings->visible != window->cfg.visible) {
972        rc = BVDC_Window_SetVisibility(windowVdc, settings->visible);
973        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowCfg;}
974        window->syncStatus.started = settings->visible;
975        window->syncStatus.visible = settings->visible;
976        callSync = true;
977        window->layoutChanged = true;
978    }
979
980    if(force || settings->zorder != window->cfg.zorder) {
981        rc = BVDC_Window_SetZOrder(windowVdc, settings->zorder);
982        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowCfg;}
983        window->layoutChanged = true;
984    }
985
986    if(force || settings->alpha != window->cfg.alpha ||
987                settings->sourceBlendFactor != window->cfg.sourceBlendFactor ||
988                settings->destBlendFactor != window->cfg.destBlendFactor ||
989                settings->constantAlpha != window->cfg.constantAlpha)
990    {
991        rc = BVDC_Window_SetAlpha(windowVdc, settings->alpha);
992        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowCfg;}
993
994        BDBG_CASSERT(NEXUS_CompositorBlendFactor_eMax-1 == BVDC_BlendFactor_eOneMinusConstantAlpha);
995        rc = BVDC_Window_SetBlendFactor( windowVdc, settings->sourceBlendFactor, settings->destBlendFactor, settings->constantAlpha);
996        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_windowCfg;}
997    }
998
999    /* internally call SetSettings functions which may have been deferred because the VDC window didn't exist */
1000    if(force){
1001        NEXUS_VideoAdj_P_ApplySetSettings(window);
1002        NEXUS_PictureCtrl_P_ApplySetSettings(window);
1003        if (window->afdSet) {
1004            rc = NEXUS_VideoWindow_SetAfdSettings(window, &window->afdSettings);
1005            if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_windowCfg;}
1006        }
1007    }
1008
1009    if (force ||
1010        settings->letterBoxDetect != window->cfg.letterBoxDetect ||
1011        settings->letterBoxAutoCut != window->cfg.letterBoxAutoCut)
1012    {
1013        if (settings->letterBoxDetect == true) {
1014            rc = BVDC_Window_EnableBoxDetect(windowVdc, NEXUS_VideoWindow_P_LboxCallbackFunc_isr, (void *)window, 0, settings->letterBoxAutoCut);
1015            if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowCfg;}
1016        }
1017        else {
1018            rc = BVDC_Window_DisableBoxDetect(windowVdc);
1019            if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowCfg;}
1020        }
1021    }
1022
1023    if (force || settings->delay != window->cfg.delay) {
1024        /* NOTE: BVDC_Window_SetDelayOffset is also set in NEXUS_VideoWindow_SetSyncSettings_priv */
1025        rc = BVDC_Window_SetDelayOffset(windowVdc, settings->delay + window->syncSettings.delay);
1026        if (rc) {return BERR_TRACE(rc);}
1027    }
1028
1029    /* Always validate content mode when dynamic RTS is active.  Some usage modes override this setting. */
1030    if (force || g_NEXUS_DisplayModule_State.moduleSettings.handleDynamicRts || settings->contentMode != window->cfg.contentMode ||
1031        BKNI_Memcmp(&settings->scaleFactorRounding, &window->cfg.scaleFactorRounding, sizeof(settings->scaleFactorRounding)))
1032    {
1033        BVDC_PanScanType panScanType = BVDC_PanScanType_eDisable;
1034        BVDC_AspectRatioMode aspectRatioMode;
1035
1036        if (force || settings->contentMode != window->cfg.contentMode) {
1037            /* if the user changed layout, we need to recompute */
1038            window->layoutChanged = true;
1039        }
1040
1041        rc = BVDC_Window_SetScaleFactorRounding( windowVdc,
1042            settings->scaleFactorRounding.enabled?settings->scaleFactorRounding.horizontalTolerance:0,
1043            settings->scaleFactorRounding.enabled?settings->scaleFactorRounding.verticalTolerance:0);
1044        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_windowCfg; }
1045
1046        switch(settings->contentMode) {
1047        case NEXUS_VideoWindowContentMode_ePanScan:
1048            panScanType = BVDC_PanScanType_eStream;
1049            aspectRatioMode = BVDC_AspectRatioMode_eUseAllDestination;
1050            break;
1051        case NEXUS_VideoWindowContentMode_ePanScanWithoutCorrection:
1052            panScanType = BVDC_PanScanType_eStream;
1053            aspectRatioMode = BVDC_AspectRatioMode_eBypass;
1054            break;
1055        case NEXUS_VideoWindowContentMode_eZoom:
1056            aspectRatioMode = BVDC_AspectRatioMode_eUseAllDestination;
1057            break;
1058        case NEXUS_VideoWindowContentMode_eBox:
1059            aspectRatioMode = BVDC_AspectRatioMode_eUseAllSource;
1060            break;
1061        default:
1062        case NEXUS_VideoWindowContentMode_eFullNonLinear:
1063        case NEXUS_VideoWindowContentMode_eFull:
1064            aspectRatioMode = BVDC_AspectRatioMode_eBypass;
1065            break;
1066        }
1067
1068        if ( window->restrictions.forceBox && aspectRatioMode != BVDC_AspectRatioMode_eUseAllSource )
1069        {
1070            BDBG_WRN(("Current usage mode requires letter/pillarbox output.  Setting window content mode to NEXUS_VideoWindowContentMode_eBox."));
1071            aspectRatioMode = BVDC_AspectRatioMode_eUseAllSource;
1072        }
1073        else if ( window->restrictions.forceFull && aspectRatioMode != BVDC_AspectRatioMode_eBypass )
1074        {
1075            BDBG_WRN(("Current usage mode requires full output mode.  Setting window content mode to NEXUS_VideoWindowContentMode_eFull."));
1076            aspectRatioMode = BVDC_AspectRatioMode_eBypass;
1077        }
1078
1079        BDBG_MSG(("window %p pan scan %d aspect ratio %d",windowVdc,panScanType,aspectRatioMode));
1080        rc = BVDC_Window_SetPanScanType(windowVdc, panScanType);
1081        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_windowCfg; }
1082
1083        rc = BVDC_Window_SetAspectRatioMode(windowVdc, aspectRatioMode);
1084        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_windowCfg; }
1085    }
1086
1087    isFullScreen = settings->position.x == 0 &&
1088                 settings->position.y == 0 &&
1089                 window->display->displayRect.width == settings->position.width &&
1090                 window->display->displayRect.height == settings->position.height;
1091
1092#ifndef B_HAS_LEGACY_VDC
1093    if (force ||
1094        !NEXUS_P_Display_RectEqual(&window->cfg.position, &settings->position) ||
1095        settings->contentMode != window->cfg.contentMode)
1096    {
1097        unsigned scalerWidth = (isFullScreen && (settings->contentMode==NEXUS_VideoWindowContentMode_eFullNonLinear)) ? settings->position.width/2 : 0;
1098        rc = BVDC_Window_SetNonLinearScl(windowVdc, scalerWidth, 0);
1099        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_windowCfg; }
1100    }
1101#endif
1102    if(force || !NEXUS_P_Display_RectEqual(&window->cfg.position, &settings->position) ||
1103            !NEXUS_P_Display_RectEqual(&window->cfg.clipBase, &settings->clipBase) ||
1104            !NEXUS_P_Display_RectEqual(&window->cfg.clipRect, &settings->clipRect)
1105            )
1106    {
1107        NEXUS_Rect scalerRect;
1108
1109        callSync = true;
1110        window->layoutChanged = true;
1111        window->syncStatus.fullScreen = isFullScreen;
1112
1113        rc = BVDC_Window_SetDstRect(windowVdc, settings->position.x, settings->position.y, settings->position.width, settings->position.height);
1114        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowDimensions;}
1115
1116        rc = NEXUS_Display_P_GetScalerRect(settings, &scalerRect);
1117        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowDimensions;}
1118
1119        BDBG_MSG(("NEXUS_VideoWindow_P_SetVdcSettings:%#lx scaler output [%u:%u x %u:%u]", (unsigned long)window, scalerRect.x, scalerRect.y, scalerRect.width, scalerRect.height));
1120        rc = BVDC_Window_SetScalerOutput(windowVdc, scalerRect.x, scalerRect.y, scalerRect.width, scalerRect.height);
1121        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowDimensions;}
1122    }
1123
1124    if(force ||
1125       window->cfg.sourceClip.left != settings->sourceClip.left ||
1126       window->cfg.sourceClip.right != settings->sourceClip.right ||
1127       window->cfg.sourceClip.top != settings->sourceClip.top ||
1128       window->cfg.sourceClip.bottom != settings->sourceClip.bottom )
1129    {
1130        rc = BVDC_Window_SetSrcClip(windowVdc, settings->sourceClip.left, settings->sourceClip.right, settings->sourceClip.top, settings->sourceClip.bottom);
1131        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowDimensions;}
1132    }
1133
1134#ifndef B_HAS_LEGACY_VDC
1135    if (force && window->colorMatrixSet) {
1136        rc = BVDC_Window_SetColorMatrix(windowVdc, window->colorMatrixOverride, window->colorMatrix.coeffMatrix, window->colorMatrix.shift);
1137        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowCfg;}
1138    }
1139#endif
1140#if NEXUS_HAS_CM3D
1141    if (force && window->colorMatrixASet) {
1142        rc = BVDC_Window_SetColorMatrixNonLinearA(windowVdc, window->colorMatrixAOverride, window->colorMatrixA.coeffMatrix, window->colorMatrixA.shift);
1143        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowCfg;}
1144    }
1145    if (force && window->colorMatrixBSet) {
1146        rc = BVDC_Window_SetColorMatrixNonLinearB(windowVdc, window->colorMatrixBOverride, window->colorMatrixB.coeffMatrix, window->colorMatrixB.shift);
1147        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowCfg;}
1148    }
1149    if (force && window->colorMatrixCSet) {
1150        rc = BVDC_Window_SetColorMatrixNonLinearC(windowVdc, window->colorMatrixCOverride, window->colorMatrixC.coeffMatrix, window->colorMatrixC.shift);
1151        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowCfg;}
1152    }
1153#endif
1154#if NEXUS_NUM_MOSAIC_DECODES
1155    if (force || window->cfg.clearRect.enabled != settings->clearRect.enabled ||
1156        window->cfg.clearRect.position.x != settings->clearRect.position.x ||
1157        window->cfg.clearRect.position.y != settings->clearRect.position.y ||
1158        window->cfg.clearRect.position.width != settings->clearRect.position.width ||
1159        window->cfg.clearRect.position.height != settings->clearRect.position.height ||
1160        window->cfg.clearRect.color != settings->clearRect.color)
1161    {
1162        BVDC_MosaicConfiguration mosaicCfg;
1163        BKNI_Memset(&mosaicCfg, 0, sizeof(mosaicCfg));
1164        if (!settings->clearRect.enabled) {
1165            /* do the minimum if disabling */
1166            BVDC_Window_SetMosaicConfiguration(windowVdc, false, &mosaicCfg);
1167        }
1168        else {
1169            BVDC_Rect clearRect;
1170            bool mosaicMode;
1171            mosaicCfg.bVideoInMosaics = false;
1172            mosaicCfg.bClearRectByMaskColor = true;
1173            mosaicCfg.ulClearRectAlpha = (settings->clearRect.color >> 24) & 0xff;
1174            mosaicCfg.ulMaskColorRed = (settings->clearRect.color >> 16) & 0xff;
1175            mosaicCfg.ulMaskColorGreen = (settings->clearRect.color >> 8) & 0xff;
1176            mosaicCfg.ulMaskColorBlue = (settings->clearRect.color >> 0) & 0xff;
1177            BVDC_Window_SetMosaicConfiguration(windowVdc, settings->clearRect.enabled, &mosaicCfg);
1178
1179            clearRect.lLeft = settings->clearRect.position.x;
1180            clearRect.lTop = settings->clearRect.position.y;
1181            clearRect.ulWidth = settings->clearRect.position.width;
1182            clearRect.ulHeight = settings->clearRect.position.height;
1183            BVDC_Window_SetMosaicDstRects(windowVdc, 1, &clearRect);
1184
1185            mosaicMode = settings->clearRect.enabled;
1186            BVDC_Window_SetMosaicRectsVisibility(windowVdc, 1, &mosaicMode);
1187        }
1188    }
1189#endif
1190
1191    if (force ||
1192        window->cfg.window3DSettings.rightViewOffset != settings->window3DSettings.rightViewOffset) {
1193        rc = BVDC_Window_SetDstRightRect(windowVdc, settings->window3DSettings.rightViewOffset);
1194        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_windowCfg;}
1195    }
1196
1197
1198    if (callSync && window->syncSettings.startCallback_isr) {
1199        BKNI_EnterCriticalSection();
1200        (*window->syncSettings.startCallback_isr)(window->syncSettings.callbackContext, 0);
1201        BKNI_LeaveCriticalSection();
1202    }
1203
1204    g_NEXUS_DisplayModule_State.updateMode = saveUpdateMode;
1205    return BERR_SUCCESS;
1206
1207err_windowCfg:
1208    g_NEXUS_DisplayModule_State.updateMode = saveUpdateMode;
1209    return rc;
1210
1211err_windowDimensions:
1212    BDBG_ERR(("Invalid window %d dimensions: position(%d,%d,%d,%d), clipRect(%d,%d,%d,%d), clipBase(%d,%d,%d,%d)",
1213        window->index,
1214        settings->position.x,settings->position.y,settings->position.width,settings->position.height,
1215        settings->clipRect.x,settings->clipRect.y,settings->clipRect.width,settings->clipRect.height,
1216        settings->clipBase.x,settings->clipBase.y,settings->clipBase.width,settings->clipBase.height));
1217    g_NEXUS_DisplayModule_State.updateMode = saveUpdateMode;
1218    return rc;
1219}
1220
1221static void NEXUS_VideoWindow_P_DelayCallback_isr(void *data, int iParm2, void * pvVdcData)
1222{
1223    NEXUS_VideoWindowHandle window = (NEXUS_VideoWindowHandle)data;
1224    const BVDC_Window_CallbackData * pCbData = (const BVDC_Window_CallbackData *)pvVdcData;
1225    const BVDC_Window_CallbackMask * pMask = &pCbData->stMask;
1226
1227    BSTD_UNUSED(iParm2);
1228
1229    /* record the status for GetStatus calls */
1230    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
1231    window->status.delay = pCbData->ulVsyncDelay;
1232    if (window->display->status.refreshRate) {
1233        window->status.phaseDelay = pCbData->ulDriftDelay; /* total delay in microseconds */
1234        window->status.phaseDelay -= window->status.delay * (1000000*1000/window->display->status.refreshRate); /* subtract out 'delay' portion */
1235    }
1236    else {
1237        window->status.phaseDelay = 0;
1238    }
1239
1240    if (window->status.outputRect.x != pCbData->stOutputRect.lLeft ||
1241        window->status.outputRect.y != pCbData->stOutputRect.lTop ||
1242        window->status.outputRect.width != pCbData->stOutputRect.ulWidth ||
1243        window->status.outputRect.height != pCbData->stOutputRect.ulHeight)
1244    {
1245        window->status.outputRect.x = pCbData->stOutputRect.lLeft;
1246        window->status.outputRect.y = pCbData->stOutputRect.lTop;
1247        window->status.outputRect.width = pCbData->stOutputRect.ulWidth;
1248        window->status.outputRect.height = pCbData->stOutputRect.ulHeight;
1249        NEXUS_IsrCallback_Fire_isr(window->outputRectChangedCallback);
1250    }
1251
1252    if (pMask->bVsyncDelay && window->syncSettings.delayCallback_isr) {
1253        (*window->syncSettings.delayCallback_isr)(window->syncSettings.callbackContext, window->status.delay);
1254    }
1255}
1256
1257BERR_Code
1258NEXUS_VideoWindow_P_CreateVdcWindow(NEXUS_VideoWindowHandle window, const NEXUS_VideoWindowSettings *cfg)
1259{
1260    BERR_Code rc;
1261    NEXUS_DisplayHandle display;
1262#ifndef B_HAS_LEGACY_VDC
1263    BVDC_Window_Settings windowCfg;
1264#endif
1265    NEXUS_VideoInput_P_Link *link;
1266
1267    BDBG_OBJECT_ASSERT(window->input, NEXUS_VideoInput);
1268    link = window->input->destination;
1269    BDBG_OBJECT_ASSERT(link, NEXUS_VideoInput_P_Link);
1270    BDBG_ASSERT(link->sourceVdc);
1271    BDBG_OBJECT_ASSERT(window->display, NEXUS_Display);
1272    display = window->display;
1273    BDBG_ASSERT(cfg);
1274
1275    BDBG_MSG((">%s(%d) window: %ux%u display=%#x window=%#x", link->id>=BAVC_SourceId_eHdDvi0?"avc/hdmi": link->id==BAVC_SourceId_eVdec0?"analog": link->id==BAVC_SourceId_e656In0?"656": "other(mpeg?)", (int)link->id, cfg->position.width, cfg->position.height, (unsigned)display, (unsigned)window));
1276
1277#ifndef B_HAS_LEGACY_VDC
1278    rc = BVDC_Window_GetDefaultSettings(window->windowId, &windowCfg);
1279    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_window;}
1280
1281    /*
1282     * This is for the cases where the application is setting the per window heap using Set Window Settings API
1283     */
1284    if (cfg->heap && cfg->heap != pVideo->heap) {
1285        window->vdcHeap = windowCfg.hHeap = NEXUS_Display_P_CreateHeap(cfg->heap);
1286
1287    }
1288    else
1289    {
1290        unsigned windowHeapIndex = pVideo->moduleSettings.videoWindowHeapIndex[window->display->index][window->index];
1291        BDBG_MSG(("window zorder %d display index %d windowheapindex %d display main heap %d",
1292            window->index,window->display->index,windowHeapIndex,pVideo->moduleSettings.primaryDisplayHeapIndex ));
1293        if(pVideo->moduleSettings.primaryDisplayHeapIndex != windowHeapIndex)
1294        {
1295           window->vdcHeap= windowCfg.hHeap = NEXUS_Display_P_CreateHeap(g_pCoreHandles->nexusHeap[windowHeapIndex]);
1296        }
1297    }
1298#if BCHP_CHIP != 7403
1299    windowCfg.bAllocFullScreen = cfg->allocateFullScreen;
1300#endif
1301
1302    if (cfg->minimumSourceFormat != NEXUS_VideoFormat_eUnknown) {
1303        BFMT_VideoFmt fmt;
1304        rc = NEXUS_P_VideoFormat_ToMagnum(cfg->minimumSourceFormat, &fmt);
1305        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_window;}
1306        windowCfg.pMinSrcFmt = BFMT_GetVideoFormatInfoPtr(fmt);
1307    }
1308    if (cfg->minimumDisplayFormat != NEXUS_VideoFormat_eUnknown) {
1309        BFMT_VideoFmt fmt;
1310        rc = NEXUS_P_VideoFormat_ToMagnum(cfg->minimumDisplayFormat, &fmt);
1311        if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_window;}
1312        windowCfg.pMinDspFmt = BFMT_GetVideoFormatInfoPtr(fmt);
1313    }
1314
1315    /* This causes MAD to allocate 5 fields. This allows apps to be written using NEXUS_VideoWindowGameMode_e5Fields_ForceSpatial instead of having
1316    to dynamically learn how many buffers are in use in order to use game mode. */
1317    windowCfg.bDeinterlacerAllocFull = true;
1318
1319    rc = BVDC_Window_Create( display->compositor, &window->vdcState.window,
1320                             (display->index < 2) ? window->windowId : BVDC_WindowId_eAuto,
1321                             link->sourceVdc, &windowCfg);
1322    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_window;}
1323    BDBG_ASSERT(window->vdcState.window);
1324#else
1325    rc = BVDC_Window_Create( display->compositor, &window->vdcState.window, link->sourceVdc);
1326    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); goto err_window;}
1327    BDBG_ASSERT(window->vdcState.window);
1328#endif
1329
1330    rc = BVDC_Window_InstallCallback(window->vdcState.window, NEXUS_VideoWindow_P_DelayCallback_isr, window, 0);
1331    if (rc) {
1332        rc = BERR_TRACE(rc);
1333        goto err_postcreate;
1334    }
1335
1336    /* Do not apply any Nexus settings to the window here. See NEXUS_VideoWindow_P_SetVdcSettings for that code. */
1337
1338    BDBG_MSG(("<window:%#x", window->vdcState.window));
1339    return BERR_SUCCESS;
1340
1341err_postcreate:
1342    BVDC_Window_Destroy(window->vdcState.window);
1343    window->vdcState.window = NULL;
1344err_window:
1345    return rc;
1346}
1347
1348
1349void
1350NEXUS_VideoWindow_P_DestroyVdcWindow(NEXUS_VideoWindowHandle window)
1351{
1352    BERR_Code rc;
1353
1354    BDBG_ASSERT(window->vdcState.window);
1355    rc = BVDC_Window_Destroy(window->vdcState.window);
1356    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); }
1357    window->vdcState.window = NULL;
1358
1359    /* may need to throw SetMasterFrameRate to other window */
1360    (void)NEXUS_VideoWindow_P_ConfigMasterFrameRate(window, &window->display->cfg, &window->cfg);
1361
1362    if(g_NEXUS_DisplayModule_State.updateMode != NEXUS_DisplayUpdateMode_eAuto) { rc = BERR_TRACE(NEXUS_NOT_SUPPORTED);}
1363    rc = BVDC_ApplyChanges(pVideo->vdc);
1364    if (rc!=BERR_SUCCESS) { rc = BERR_TRACE(rc); }
1365    return;
1366}
1367
1368void
1369NEXUS_VideoWindow_GetSettings(NEXUS_VideoWindowHandle window, NEXUS_VideoWindowSettings *settings)
1370{
1371    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
1372    BDBG_ASSERT(settings);
1373    *settings = window->cfg;
1374    return;
1375}
1376
1377NEXUS_Error
1378NEXUS_VideoWindow_AddInput(NEXUS_VideoWindowHandle window, NEXUS_VideoInput input)
1379{
1380    NEXUS_Error rc;
1381    NEXUS_VideoInput_P_Link *link;
1382
1383    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
1384    BDBG_OBJECT_ASSERT(input, NEXUS_VideoInput);
1385
1386    /* verify there is no existing connection for this window */
1387    if (window->input!=NULL) {
1388        return BERR_TRACE(NEXUS_NOT_SUPPORTED);
1389    }
1390
1391#if NEXUS_NUM_MOSAIC_DECODES
1392    if (window->mosaic.parent) {
1393        rc = NEXUS_VideoWindow_P_AddMosaicInput(window, input);
1394        if (rc) return BERR_TRACE(rc);
1395        /* mosaics can now be connected as a normal input/input, but do not create the VDC window */
1396    }
1397#endif
1398
1399    link = NEXUS_VideoInput_P_Get(input);
1400    if (!link) {
1401        /* The only case where NEXUS_VideoInput_P_Get can fail is if this NEXUS_VideoInput is
1402        connected to another module. As of now, that case doesn't exist, but this check would be needed. */
1403        return BERR_TRACE(NEXUS_NOT_SUPPORTED);
1404    }
1405
1406    /* we must connect before calling setup. this allows inputs to create/destroy their VDC source
1407    on connect/disconnect instead of requiring them to always be created. */
1408    if (link->ref_cnt == 0) {
1409        rc = NEXUS_VideoInput_P_Connect(input, window);
1410        if(rc!=BERR_SUCCESS) {rc=BERR_TRACE(rc);goto err_connect;}
1411    }
1412    link->ref_cnt++;
1413    window->input = input;
1414    BDBG_ASSERT(input->destination == link);
1415
1416#if NEXUS_NUM_MOSAIC_DECODES
1417    if (!window->mosaic.parent)
1418#endif
1419    {
1420        rc = NEXUS_VideoWindow_P_CreateVdcWindow(window, &window->cfg);
1421        if(rc!=BERR_SUCCESS) {rc=BERR_TRACE(rc);goto err_setup;}
1422        BDBG_ASSERT(window->vdcState.window);
1423
1424        /* now that the window is created, we can apply settings */
1425        rc = NEXUS_VideoWindow_P_SetVdcSettings(window, &window->cfg, true);
1426        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_setsettings;}
1427
1428        rc = NEXUS_Display_P_ApplyChanges();
1429        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_applychanges;}
1430    }
1431
1432    BKNI_EnterCriticalSection();
1433    NEXUS_VideoInput_P_TriggerSourceChanged_isr(link, false);
1434    BKNI_LeaveCriticalSection();
1435
1436    /* update display settings on the input side */
1437    BDBG_ASSERT(window->display);
1438    NEXUS_Display_P_VideoInputDisplayUpdate(input, window, &window->display->cfg);
1439
1440#if NEXUS_NUM_MOSAIC_DECODES
1441    if (window->mosaic.parent) {
1442        rc = NEXUS_VideoWindow_P_ApplyMosaic(window->mosaic.parent);
1443        if (rc) {rc = BERR_TRACE(rc);} /* fall through */
1444    }
1445#endif
1446
1447    return 0;
1448
1449err_applychanges:
1450err_setsettings:
1451err_setup:
1452    BDBG_ASSERT(link->ref_cnt>0);
1453    if(--link->ref_cnt==0) {
1454        NEXUS_VideoInput_P_Disconnect(window->input);
1455    }
1456err_connect:
1457    {
1458        BERR_Code rc = BVDC_AbortChanges(pVideo->vdc);
1459        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);}
1460    }
1461    window->input = NULL;
1462    return rc;
1463}
1464
1465NEXUS_Error
1466NEXUS_VideoWindow_RemoveInput(NEXUS_VideoWindowHandle window, NEXUS_VideoInput input)
1467{
1468    NEXUS_VideoInput_P_Link *link;
1469
1470    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
1471    BDBG_OBJECT_ASSERT(input, NEXUS_VideoInput);
1472    if(window->input!=input) { return BERR_TRACE(NEXUS_INVALID_PARAMETER); }
1473
1474    link = NEXUS_VideoInput_P_Get(window->input);
1475    if (!link) {
1476        BDBG_ERR(("NEXUS_VideoWindow_RemoveInput:%#lx invalid input %#lx", (unsigned long)window, (unsigned long)window->input));
1477        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
1478    }
1479
1480#if NEXUS_NUM_MOSAIC_DECODES
1481    if (window->mosaic.parent) {
1482        NEXUS_VideoWindow_P_RemoveMosaicInput(window, input);
1483    }
1484    else 
1485#endif
1486    {
1487        NEXUS_VideoWindow_P_DestroyVdcWindow(window);
1488    }
1489
1490    BDBG_ASSERT(link->ref_cnt>0);
1491    if (--link->ref_cnt==0) {
1492        NEXUS_VideoInput_P_Disconnect(window->input);
1493       
1494#if NEXUS_NUM_MOSAIC_DECODES
1495        /* because each mosaic's link copies the VDC source of the parent, we must shutdown the mosaic on
1496        the last disconnect to clear the copy. */
1497        if (window->mosaic.parent) {
1498            NEXUS_VideoInput_Shutdown(input);
1499        }
1500#endif
1501    }
1502   
1503    window->input = NULL;
1504
1505#ifndef B_HAS_LEGACY_VDC
1506    if (window->vdcHeap) {
1507        NEXUS_Display_P_DestroyHeap(window->vdcHeap);
1508        window->vdcHeap = NULL;
1509    }
1510#endif
1511
1512    return NEXUS_SUCCESS;
1513}
1514
1515void
1516NEXUS_VideoWindow_RemoveAllInputs(NEXUS_VideoWindowHandle window)
1517{
1518    NEXUS_Error rc;
1519
1520    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
1521
1522    if(window->input) {
1523        rc = NEXUS_VideoWindow_RemoveInput(window, window->input);
1524        if (rc!=BERR_SUCCESS) {rc=BERR_TRACE(rc);}
1525    }
1526    return;
1527}
1528
1529NEXUS_Error
1530NEXUS_VideoWindow_SetSettings(NEXUS_VideoWindowHandle window, const NEXUS_VideoWindowSettings *settings)
1531{
1532    BERR_Code rc = BERR_SUCCESS;
1533
1534    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
1535    BDBG_OBJECT_ASSERT(window->display, NEXUS_Display);
1536    BDBG_ASSERT(settings);
1537
1538#if NEXUS_NUM_MOSAIC_DECODES
1539    /* don't allow this if a mosaic parent */
1540    if (BLST_S_FIRST(&window->mosaic.children)) {
1541        return BERR_TRACE(NEXUS_NOT_AVAILABLE);
1542    }
1543#endif
1544
1545    if (window->vdcState.window)
1546    {
1547        NEXUS_VideoWindowSettings oldSettings;
1548        rc = NEXUS_VideoWindow_P_SetVdcSettings(window, settings, false);
1549        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);goto err_setsettings;}
1550
1551        /* We must save the settings here for VDB to read them in ApplyChanges.  If ApplyChanges fails, we will roll back. */
1552        oldSettings = window->cfg;
1553        window->cfg = *settings;
1554
1555        rc = NEXUS_Display_P_ApplyChanges();
1556        if (rc!=BERR_SUCCESS)
1557        {
1558            rc = BERR_TRACE(rc);
1559            window->cfg = oldSettings;
1560            goto err_applychanges;
1561        }
1562    }
1563    else
1564    {
1565        /* Just store the settings */
1566        window->cfg = *settings;
1567    }
1568
1569    if (window->letterBoxDetectionCallback) {
1570        NEXUS_IsrCallback_Set(window->letterBoxDetectionCallback, &settings->letterBoxDetectionChange);
1571    }
1572    if (window->outputRectChangedCallback) {
1573        NEXUS_IsrCallback_Set(window->outputRectChangedCallback, &settings->outputRectChanged);
1574    }
1575
1576#if NEXUS_NUM_MOSAIC_DECODES
1577    if (window->mosaic.parent) {
1578        NEXUS_VideoWindow_P_ApplyMosaic(window->mosaic.parent);
1579    }
1580#endif
1581    return rc;
1582err_applychanges:
1583err_setsettings:
1584    {
1585        BERR_Code rc = BVDC_AbortChanges(pVideo->vdc);
1586        if (rc!=BERR_SUCCESS) {rc = BERR_TRACE(rc);}
1587    }
1588    return rc;
1589}
1590
1591NEXUS_SurfaceHandle NEXUS_VideoWindow_CaptureVideoBuffer( NEXUS_VideoWindowHandle window )
1592{
1593    BVDC_Window_Handle  windowVDC;
1594    BVDC_Window_CapturedImage captureBuffer;
1595    BERR_Code rc = BERR_SUCCESS;
1596    NEXUS_SurfaceHandle surface;
1597    unsigned tries = 5;
1598
1599    BDBG_ENTER(NEXUS_VideoWindow_CaptureVideoBuffer);
1600
1601    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
1602    windowVDC = window->vdcState.window;
1603
1604    if (NULL == windowVDC) /* window not connected */
1605    {
1606        BDBG_ERR(("Window not connnected"));
1607        BDBG_LEAVE(NEXUS_VideoWindow_CaptureVideoBuffer);
1608        rc = BERR_TRACE(NEXUS_NOT_SUPPORTED);
1609        return NULL;
1610    }
1611
1612    if (window->captureBuffer) {
1613        BDBG_ERR(("must return currently captured surface before capturing another"));
1614        return NULL;
1615    }
1616
1617    /* set capture buffers used, should apply changes to take effect */
1618    rc = BVDC_Window_SetUserCaptureBufferCount(windowVDC, 1);
1619    if (rc) {rc=BERR_TRACE(rc);return NULL;}
1620
1621    if(g_NEXUS_DisplayModule_State.updateMode != NEXUS_DisplayUpdateMode_eAuto) { rc = BERR_TRACE(NEXUS_NOT_SUPPORTED);}
1622    rc = BVDC_ApplyChanges(g_NEXUS_DisplayModule_State.vdc);
1623    if (rc) {rc=BERR_TRACE(rc);return NULL;}
1624
1625    /* now that we've allocated a user capture buffer inside VDC, we must succeed or goto error_free_buffer to free that buffer. */
1626
1627    /* Get the video buffer from VDC.
1628       Note that BVDC_Window_GetBuffer will set captureBuffer.hCaptureBuffer even if rc is non-zero.
1629       This is atypical behavior but must be accounted for. */
1630    while (tries--) {
1631        rc = BVDC_Window_GetBuffer(windowVDC, &captureBuffer);
1632        if (rc == BVDC_ERR_NO_AVAIL_CAPTURE_BUFFER) {
1633            /* Only a buffer at certain postion can be returned and it must have valid picture captured on it. Without this, tearing occurs.
1634            This tries just a few times with a slight delay. */
1635            BKNI_Delay(10 * 1000);
1636        }
1637        else {
1638            break;
1639        }
1640    }
1641    if ((rc != BERR_SUCCESS) || (captureBuffer.hCaptureBuffer == NULL))
1642    {
1643        rc = BERR_TRACE(rc);
1644        goto error_free_buffer;
1645    }
1646
1647    /* store for later return to VDC. a new nexus API is needed to return it to the user. */
1648    window->hRCaptureBuffer = captureBuffer.hRCaptureBuffer;
1649
1650    NEXUS_Module_Lock(g_NEXUS_DisplayModule_State.modules.surface);
1651    surface = NEXUS_Surface_CreateFromMagnum_priv(captureBuffer.hCaptureBuffer);
1652    NEXUS_Module_Unlock(g_NEXUS_DisplayModule_State.modules.surface);
1653    if(!surface) {
1654        BDBG_ERR(("unknown surface. was this a video capture buffer?"));
1655        goto error_free_buffer;
1656    }
1657
1658    /* Save the buffer in the window private context */
1659    window->captureBuffer = surface;
1660
1661    BDBG_LEAVE(NEXUS_VideoWindow_CaptureVideoBuffer);
1662
1663    return surface;
1664
1665error_free_buffer:
1666    if (captureBuffer.hCaptureBuffer != NULL) {
1667        rc = BVDC_Window_ReturnBuffer(windowVDC, &captureBuffer);
1668        if (rc) {rc = BERR_TRACE(rc);} /* fall through */
1669        window->hRCaptureBuffer = NULL;
1670        rc = BVDC_ApplyChanges(g_NEXUS_DisplayModule_State.vdc);
1671        if (rc) {rc = BERR_TRACE(rc);} /* fall through */
1672    }
1673    rc = BVDC_Window_SetUserCaptureBufferCount(windowVDC, 0);
1674    if (rc) {rc = BERR_TRACE(rc);} /* fall through */
1675    rc = BVDC_ApplyChanges(g_NEXUS_DisplayModule_State.vdc);
1676    if (rc) {rc = BERR_TRACE(rc);} /* fall through */
1677    return NULL;
1678
1679}   /* NEXUS_VideoWindow_CaptureVideoBuffer() */
1680
1681NEXUS_Error NEXUS_VideoWindow_ReleaseVideoBuffer( NEXUS_VideoWindowHandle window, NEXUS_SurfaceHandle surface )
1682{
1683    BVDC_Window_Handle  windowVDC;
1684    BERR_Code rc = BERR_SUCCESS;
1685    BSUR_Surface_Handle magnumSurface;
1686
1687    BDBG_ENTER(NEXUS_VideoWindow_ReleaseVideoBuffer);
1688
1689    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
1690    windowVDC = window->vdcState.window;
1691    BDBG_ASSERT(surface);
1692
1693    if(surface != window->captureBuffer) {
1694        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
1695    }
1696
1697    if (NULL == windowVDC) /* window not connected */
1698    {
1699        BDBG_ERR(("Window not connnected"));
1700        BDBG_LEAVE(NEXUS_VideoWindow_ReleaseVideoBuffer);
1701        return BERR_TRACE(NEXUS_UNKNOWN);
1702    }
1703
1704    NEXUS_Module_Lock(g_NEXUS_DisplayModule_State.modules.surface);
1705    magnumSurface = NEXUS_Surface_GetSurface_priv(surface);
1706    NEXUS_Surface_ReleaseSurface_priv(surface);
1707    NEXUS_Module_Unlock(g_NEXUS_DisplayModule_State.modules.surface);
1708    BDBG_ASSERT(magnumSurface);
1709    window->captureBuffer = NULL;
1710
1711    {
1712        BVDC_Window_CapturedImage captureBuffer;
1713        BKNI_Memset(&captureBuffer, 0, sizeof(captureBuffer));
1714        captureBuffer.hCaptureBuffer = magnumSurface;
1715        captureBuffer.hRCaptureBuffer = window->hRCaptureBuffer;
1716        rc = BVDC_Window_ReturnBuffer(windowVDC, &captureBuffer);
1717        if (rc) return BERR_TRACE(rc);
1718        window->hRCaptureBuffer = NULL;
1719    }
1720    if(g_NEXUS_DisplayModule_State.updateMode != NEXUS_DisplayUpdateMode_eAuto) { rc = BERR_TRACE(NEXUS_NOT_SUPPORTED);}
1721    rc = BVDC_ApplyChanges(g_NEXUS_DisplayModule_State.vdc);
1722    if (rc) return BERR_TRACE(rc);
1723    rc = BVDC_Window_SetUserCaptureBufferCount(windowVDC, 0);
1724    if (rc) return BERR_TRACE(rc);
1725    rc = BVDC_ApplyChanges(g_NEXUS_DisplayModule_State.vdc);
1726    if (rc) return BERR_TRACE(rc);
1727
1728    return NEXUS_SUCCESS;
1729}
1730
1731void
1732NEXUS_VideoWindow_GetSplitScreenSettings(
1733    NEXUS_VideoWindowHandle window,
1734    NEXUS_VideoWindowSplitScreenSettings *pSettings)
1735{
1736    *pSettings = window->splitScreenSettings;
1737}
1738
1739NEXUS_Error
1740NEXUS_VideoWindow_SetSplitScreenSettings(
1741    NEXUS_VideoWindowHandle window,
1742    const NEXUS_VideoWindowSplitScreenSettings *pSettings
1743    )
1744{
1745    NEXUS_Error rc;
1746    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
1747    BDBG_ASSERT(pSettings);
1748
1749    /* save for later */
1750    if (!window->vdcState.window) {
1751        window->splitScreenSettings = *pSettings;
1752        return NEXUS_SUCCESS;
1753    }
1754
1755    window->splitScreenSettings = *pSettings;
1756    rc = NEXUS_VideoWindow_P_ApplySplitScreenSettings(window);
1757    if (rc) return BERR_TRACE(rc);
1758
1759    rc = NEXUS_Display_P_ApplyChanges();
1760    if (rc) return BERR_TRACE(rc);
1761
1762    return 0;
1763}
1764
1765static NEXUS_Error NEXUS_VideoWindow_P_ApplySplitScreenSettings(NEXUS_VideoWindowHandle window)
1766{
1767#ifndef B_HAS_LEGACY_VDC
1768    BERR_Code rc;
1769    BVDC_Window_Handle windowVDC;
1770    NEXUS_VideoInput_P_Link *pLink;
1771    BVDC_Window_SplitScreenSettings winSettings;
1772    BVDC_Source_SplitScreenSettings srcSettings;
1773    NEXUS_VideoWindowSplitScreenSettings *pSettings = &window->splitScreenSettings;
1774    int i =0,j=0;
1775
1776    BDBG_ENTER(NEXUS_VideoWindow_SetSplitScreenSettings);
1777
1778    windowVDC = window->vdcState.window;
1779    BDBG_ASSERT(windowVDC);
1780    pLink = NEXUS_VideoInput_P_Get(window->input);
1781
1782    /* Check for 1st window of primary display (PEP_WINDOW restriction in BVDC_Window_SetSplitScreenMode) */
1783    if ((window->display->index == 0) && (window->windowId == BVDC_WindowId_eVideo0))
1784    {
1785        (void)BVDC_Window_GetSplitScreenMode(windowVDC, &winSettings);
1786        winSettings.eHue = pSettings->hue;
1787        winSettings.eContrast = pSettings->contrast;
1788        winSettings.eBrightness = pSettings->brightness;
1789        winSettings.eColorTemp = pSettings->colorTemp;
1790
1791        winSettings.eAutoFlesh = pSettings->autoFlesh;
1792        winSettings.eSharpness = pSettings->sharpness;
1793        winSettings.eBlueBoost = pSettings->blueBoost;
1794        winSettings.eGreenBoost = pSettings->greenBoost;
1795        winSettings.eBlueStretch = pSettings->blueStretch;
1796        winSettings.eCms = pSettings->cms;
1797        winSettings.eContrastStretch = pSettings->contrastStretch;
1798        winSettings.eCm3d = pSettings->cm3d;
1799    #if BCHP_CHIP != 7403
1800        winSettings.eAnr = pSettings->anr;
1801        winSettings.eDeJagging = pSettings->dejagging;
1802        winSettings.eDeRinging = pSettings->deringing;
1803    #endif
1804        rc = BVDC_Window_SetSplitScreenMode(windowVDC, &winSettings);
1805        if (rc) return BERR_TRACE(rc);
1806    }
1807
1808    if (pLink && pLink->sourceVdc) {
1809        (void)BVDC_Source_GetSplitScreenMode(pLink->sourceVdc, &srcSettings);
1810
1811        srcSettings.eDnr = BVDC_SplitScreenMode_eDisable;
1812
1813        for (i=0;i<NEXUS_NUM_DISPLAYS && srcSettings.eDnr==BVDC_SplitScreenMode_eDisable;i++) {
1814            for (j=0;j<NEXUS_NUM_VIDEO_WINDOWS;j++) {
1815                if (pVideo->displays[i] && pVideo->displays[i]->windows[j].input == pLink->input) {
1816                    if (pVideo->displays[i]->windows[j].splitScreenSettings.dnr) {
1817                        srcSettings.eDnr = pVideo->displays[i]->windows[j].splitScreenSettings.dnr;
1818                        BDBG_MSG(("display %d window %d DNR set to %d",i, j, srcSettings.eDnr));
1819                        break;
1820                    }
1821                }
1822            }
1823        }
1824
1825        rc = BVDC_Source_SetSplitScreenMode(pLink->sourceVdc, &srcSettings);
1826        if (rc) return BERR_TRACE(rc);
1827    }
1828#else
1829    BSTD_UNUSED(window);
1830#endif
1831    /* don't ApplyChanges here */
1832    return NEXUS_SUCCESS;
1833}
1834
1835NEXUS_VideoWindowHandle
1836NEXUS_VideoWindow_Open(NEXUS_DisplayHandle display, unsigned windowIndex)
1837{
1838    BERR_Code rc;
1839    NEXUS_VideoWindowHandle window;
1840    BDBG_OBJECT_ASSERT(display, NEXUS_Display);
1841    if(windowIndex>=sizeof(display->windows)/sizeof(display->windows[0])) {
1842        rc = BERR_TRACE(BERR_NOT_SUPPORTED);
1843        return NULL;
1844    }
1845    window = &display->windows[windowIndex];
1846
1847    if (window->open) {
1848        BDBG_ERR(("window already open"));
1849        return NULL;
1850    }
1851    window->open = true;
1852    window->letterBoxDetectionCallback = NEXUS_IsrCallback_Create(window, NULL);
1853    window->outputRectChangedCallback = NEXUS_IsrCallback_Create(window, NULL);
1854    window->index = windowIndex; /* have explicit window->index instead of VDC's windowId for dereferencing arrays, etc. */
1855    BDBG_CASSERT(BVDC_WindowId_eVideo0 == 0);
1856    BDBG_CASSERT(BVDC_WindowId_eVideo1 == 1);
1857    window->windowId = windowIndex + BVDC_WindowId_eVideo0;
1858    /* By default, there are no restrictions on capabilities.  Dynamic RTS may enforce this later. */
1859    window->restrictions.mnrBnrPermitted = window->restrictions.dcrPermitted = window->restrictions.anrPermitted = window->restrictions.madPermitted = true;
1860    window->restrictions.madFieldStore = 0xffffffff;
1861    window->restrictions.anrMaxFormat = window->restrictions.madMaxFormat = window->restrictions.maxFormat = NEXUS_PixelFormat_eUnknown;
1862    window->restrictions.forceCapture = false;
1863    window->restrictions.forceBox = window->restrictions.forceFull = false;
1864    window->rtsId = (unsigned)-1; /* Invalid */
1865
1866    if (BKNI_CreateEvent(&window->lb_event)) {
1867        BDBG_ERR(("window lb event fault"));
1868        return NULL;
1869    }
1870
1871#if NEXUS_NUM_MOSAIC_DECODES
1872    BLST_S_INIT(&window->mosaic.children);
1873#endif
1874
1875    return window;
1876}
1877
1878void
1879NEXUS_VideoWindow_Close(NEXUS_VideoWindowHandle window)
1880{
1881    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
1882    if (!window->open) {
1883        BDBG_ERR(("invalid window"));
1884    }
1885    window->open = false;
1886
1887    NEXUS_VideoWindow_RemoveAllInputs(window);
1888
1889#if NEXUS_NUM_MOSAIC_DECODES
1890    if (window->mosaic.parent) {
1891        BLST_S_REMOVE(&window->mosaic.parent->mosaic.children, window, NEXUS_VideoWindow, mosaic.link);
1892        BDBG_OBJECT_DESTROY(window, NEXUS_VideoWindow);
1893        BKNI_Free(window);
1894    }
1895    else
1896#endif
1897    {
1898#if NEXUS_NUM_MOSAIC_DECODES
1899        NEXUS_VideoWindowHandle mosaicChild;
1900        while ((mosaicChild = BLST_S_FIRST(&window->mosaic.children))) {
1901            BDBG_WRN(("NEXUS_VideoWindow_Close is automatically closing mosaic window %p", mosaicChild));
1902            nexus_unregister_NEXUS_VideoWindowHandle(nexus_display_client(), mosaicChild, false);
1903            NEXUS_VideoWindow_Close(mosaicChild);
1904        }
1905#endif
1906
1907        NEXUS_IsrCallback_Destroy(window->letterBoxDetectionCallback);
1908        NEXUS_IsrCallback_Destroy(window->outputRectChangedCallback);
1909        BKNI_DestroyEvent(window->lb_event);
1910    }
1911}
1912
1913void NEXUS_VideoWindow_GetSyncSettings_priv( NEXUS_VideoWindowHandle window, NEXUS_VideoWindowSyncSettings *pSyncSettings )
1914{
1915    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
1916    NEXUS_ASSERT_MODULE();
1917    *pSyncSettings = window->syncSettings;
1918}
1919
1920NEXUS_Error NEXUS_VideoWindow_SetSyncSettings_priv( NEXUS_VideoWindowHandle window, const NEXUS_VideoWindowSyncSettings *pSyncSettings )
1921{
1922    BERR_Code rc;
1923    BVDC_Window_Handle windowVdc = window->vdcState.window;
1924    BVDC_Window_CallbackSettings wcbs;
1925    bool hookingUp = false;
1926
1927    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
1928    NEXUS_ASSERT_MODULE();
1929
1930    if (windowVdc)
1931    {
1932        hookingUp = (window->syncSettings.startCallback_isr == NULL &&
1933            pSyncSettings->startCallback_isr != NULL);
1934        window->syncSettings = *pSyncSettings;
1935
1936        rc = BVDC_Window_GetCallbackSettings(windowVdc, &wcbs);
1937        if (rc) {return BERR_TRACE(rc);}
1938        wcbs.stMask.bDriftDelay = false;
1939        wcbs.ulLipSyncTolerance = 1000; /* usec. hardcoded threshold for bDriftDelay. */
1940#ifndef B_HAS_LEGACY_VDC
1941        wcbs.stMask.bGameModeDelay = false;
1942#endif
1943        wcbs.stMask.bVsyncDelay = true;
1944        rc = BVDC_Window_SetCallbackSettings(windowVdc, &wcbs);
1945        if (rc) {return BERR_TRACE(rc);}
1946
1947        rc = BVDC_Window_SetDelayOffset(windowVdc, window->cfg.delay + window->syncSettings.delay);
1948        if (rc) {return BERR_TRACE(rc);}
1949
1950        rc = BVDC_ApplyChanges(g_NEXUS_DisplayModule_State.vdc);
1951        if (rc) {return BERR_TRACE(rc);}
1952
1953        /* fire some callbacks to set SyncChannel's initial state */
1954        if (hookingUp) {
1955            BKNI_EnterCriticalSection();
1956            if (window->syncSettings.formatCallback_isr) {
1957                (*window->syncSettings.formatCallback_isr)(window->syncSettings.callbackContext, 0);
1958            }
1959            if (window->syncSettings.startCallback_isr) {
1960                (*window->syncSettings.startCallback_isr)(window->syncSettings.callbackContext, 0);
1961            }
1962            if (window->syncSettings.delayCallback_isr) {
1963                (*window->syncSettings.delayCallback_isr)(window->syncSettings.callbackContext, window->status.delay);
1964            }
1965            BKNI_LeaveCriticalSection();
1966        }
1967    }
1968    else
1969    {
1970        BDBG_MSG(("SetSyncSettings called with NULL VDC window"));
1971        /* TODO: save the delay and callback installation state */
1972    }
1973
1974    return 0;
1975}
1976
1977NEXUS_Error NEXUS_VideoWindow_GetSyncStatus_isr( NEXUS_VideoWindowHandle window, NEXUS_VideoWindowSyncStatus *pSyncStatus )
1978{
1979    BFMT_VideoInfo video_format_info;
1980    unsigned long ulFrameRate;
1981    NEXUS_Error rc;
1982
1983    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
1984
1985    /* translate display status on demand */
1986    rc = NEXUS_P_Display_GetMagnumVideoFormatInfo(window->display, window->display->cfg.format, &video_format_info);
1987    if (rc) {return BERR_TRACE(rc);}
1988    window->syncStatus.height = video_format_info.ulDigitalHeight;
1989    window->syncStatus.interlaced = video_format_info.bInterlaced;
1990    window->syncStatus.masterFrameRateEnabled = (window->display->cfg.frameRateMaster == window->input) || window->cfg.autoMaster;
1991    ulFrameRate = video_format_info.bInterlaced ? video_format_info.ulVertFreq / 2 : video_format_info.ulVertFreq;
1992    switch (ulFrameRate) {
1993    case 2397: window->syncStatus.frameRate = BAVC_FrameRateCode_e23_976; break;
1994    case 2400: window->syncStatus.frameRate = BAVC_FrameRateCode_e24; break;
1995    case 2500: window->syncStatus.frameRate = BAVC_FrameRateCode_e25; break;
1996    case 2997: window->syncStatus.frameRate = BAVC_FrameRateCode_e29_97; break;
1997    case 3000: window->syncStatus.frameRate = BAVC_FrameRateCode_e30; break;
1998    case 5000: window->syncStatus.frameRate = BAVC_FrameRateCode_e50; break;
1999    case 5994: window->syncStatus.frameRate = BAVC_FrameRateCode_e59_94; break;
2000    case 6000: window->syncStatus.frameRate = BAVC_FrameRateCode_e60; break;
2001    default: window->syncStatus.frameRate = BAVC_FrameRateCode_eUnknown; break;
2002    }
2003
2004    *pSyncStatus = window->syncStatus;
2005
2006    return 0;
2007}
2008
2009void NEXUS_VideoWindow_GetColorMatrix( NEXUS_VideoWindowHandle window, NEXUS_ColorMatrix *pSettings)
2010{
2011    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
2012    *pSettings = window->colorMatrix;
2013}
2014
2015NEXUS_Error NEXUS_VideoWindow_SetColorMatrix( NEXUS_VideoWindowHandle window, const NEXUS_ColorMatrix *pSettings )
2016{
2017    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
2018
2019    if (pSettings) {
2020        window->colorMatrix = *pSettings;
2021    }
2022    window->colorMatrixSet = true;
2023    window->colorMatrixOverride = pSettings != NULL;
2024#ifndef B_HAS_LEGACY_VDC
2025    if (window->vdcState.window) {
2026        BERR_Code rc;
2027        rc = BVDC_Window_SetColorMatrix(window->vdcState.window, window->colorMatrixOverride, window->colorMatrix.coeffMatrix, window->colorMatrix.shift);
2028        if (rc) return BERR_TRACE(rc);
2029
2030        rc = NEXUS_Display_P_ApplyChanges();
2031        if (rc) return BERR_TRACE(rc);
2032    }
2033#endif
2034    return 0;
2035}
2036
2037NEXUS_Error NEXUS_VideoWindow_GetStatus( NEXUS_VideoWindowHandle window, NEXUS_VideoWindowStatus *pStatus)
2038{
2039    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
2040
2041    /* window->status is incrementally updated from various isr callbacks from VDC, so we
2042    start with this copy */
2043    *pStatus = window->status;
2044
2045    /* now query immediate status */
2046    if (window->vdcState.window) {
2047        BVDC_Window_Status vdcStatus;
2048        BERR_Code rc;
2049        rc = BVDC_Window_GetStatus(window->vdcState.window, &vdcStatus);
2050        if (rc) return BERR_TRACE(rc);
2051        pStatus->isSyncLocked = vdcStatus.bSyncLock;
2052    }
2053    else {
2054        pStatus->isSyncLocked = false;
2055    }
2056
2057    return 0;
2058}
2059
2060
2061NEXUS_Error NEXUS_VideoWindow_GetLetterBoxStatus( NEXUS_VideoWindowHandle window, NEXUS_VideoWindowLetterBoxStatus *pStatus )
2062{
2063    *pStatus = window->letterBoxStatus;
2064    return 0;
2065}
2066
2067void NEXUS_GetDefaultCalculateVideoWindowPositionSettings( NEXUS_CalculateVideoWindowPositionSettings *pSettings )
2068{
2069    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
2070    pSettings->manualAspectRatioCorrection = NEXUS_VideoWindowContentMode_eFull;
2071    pSettings->sourceAspectRatio = NEXUS_AspectRatio_e4x3;
2072    pSettings->viewport.width = 1920;
2073    pSettings->viewport.height = 1080;
2074    pSettings->displayAspectRatio = NEXUS_DisplayAspectRatio_eAuto;
2075}
2076
2077NEXUS_Error NEXUS_CalculateVideoWindowPosition( const NEXUS_CalculateVideoWindowPositionSettings *pPosition,
2078    const NEXUS_VideoWindowSettings *pInputWindowSettings, NEXUS_VideoWindowSettings *pWindowSettings)
2079{
2080    unsigned clip;
2081    NEXUS_Rect viewport = pPosition->viewport; /* may need to modify for manual a/r correction */
2082    unsigned verticalClipping = pPosition->verticalClipping; /* may need to modify for manual a/r correction */
2083    unsigned horizontalClipping = pPosition->horizontalClipping; /* may need to modify for manual a/r correction */
2084    unsigned displayAr, sourceAr; /* aspect ratio in 1/100th's units (e.g. 4:3 = 4/3 = 133 */
2085    unsigned aspectNumerator, aspectDenominator;
2086
2087    *pWindowSettings = *pInputWindowSettings;
2088
2089    if (!pPosition->displayWidth || !pPosition->displayHeight) {
2090        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
2091    }
2092
2093    /* store AR as width/height in 1/100ths.
2094    This has the advantage of already being in units of a horizontal percentage for clipping-based zoom. */
2095    switch (pPosition->displayAspectRatio) {
2096    case NEXUS_DisplayAspectRatio_eAuto:
2097        displayAr = pPosition->displayWidth * 100 / pPosition->displayHeight;
2098        if (!displayAr) return BERR_TRACE(NEXUS_INVALID_PARAMETER);
2099        break;
2100    case NEXUS_DisplayAspectRatio_e4x3:
2101        displayAr = 4 * 100 / 3;
2102        break;
2103    case NEXUS_DisplayAspectRatio_e16x9:
2104        displayAr = 16 * 100 / 9;
2105        break;
2106    default:
2107        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
2108    }
2109
2110    switch (pPosition->sourceAspectRatio) {
2111    case NEXUS_AspectRatio_e4x3:
2112        sourceAr = 400 / 3;
2113        aspectNumerator = 4;
2114        aspectDenominator = 3;
2115        break;
2116    case NEXUS_AspectRatio_e16x9:
2117        sourceAr = 1600 / 9;
2118        aspectNumerator = 16;
2119        aspectDenominator = 9;
2120        break;
2121    case NEXUS_AspectRatio_eSquarePixel:
2122        /* square pixel is the same as SAR 1:1 */
2123        if (pPosition->sourceHeight) {
2124            sourceAr = pPosition->sourceWidth * 100 / pPosition->sourceHeight;
2125            aspectNumerator = pPosition->sourceWidth;
2126            aspectDenominator = pPosition->sourceHeight;
2127        }
2128        else {
2129            return BERR_TRACE(NEXUS_INVALID_PARAMETER);
2130        }
2131        break;
2132    case NEXUS_AspectRatio_e221x1:
2133        sourceAr = 221;
2134        aspectNumerator = 221;
2135        aspectDenominator = 100;
2136        break;
2137    case NEXUS_AspectRatio_e15x9:
2138        sourceAr = 1500 / 9;
2139        aspectNumerator = 15;
2140        aspectDenominator = 9;
2141        break;
2142    case NEXUS_AspectRatio_eSar:
2143        if (pPosition->sampleAspectRatio.x && pPosition->sampleAspectRatio.y && pPosition->sourceWidth && pPosition->sourceHeight) {
2144            sourceAr = pPosition->sourceWidth * 100 * pPosition->sampleAspectRatio.x / pPosition->sampleAspectRatio.y / pPosition->sourceHeight;
2145            aspectNumerator = pPosition->sourceWidth * pPosition->sampleAspectRatio.x;
2146            aspectDenominator = pPosition->sourceHeight * pPosition->sampleAspectRatio.y;
2147        }
2148        else {
2149            return BERR_TRACE(NEXUS_INVALID_PARAMETER);
2150        }
2151        break;
2152    default:
2153        sourceAr = 0;
2154        aspectNumerator = 0;
2155        aspectDenominator = 1;
2156        break;
2157    }
2158
2159    /**
2160    Manual aspect ratio correction involves either changes in the viewport or in clipping.
2161    **/
2162    switch (pPosition->manualAspectRatioCorrection) {
2163    case NEXUS_VideoWindowContentMode_eBox:
2164        if (!sourceAr) {
2165            return BERR_TRACE(NEXUS_INVALID_PARAMETER);
2166        }
2167
2168        /* if display and source ARs are equal, no letter/pillar boxing required */
2169        if(displayAr != sourceAr)
2170        {
2171            if (displayAr > sourceAr) {
2172                /* pillar box */
2173                unsigned w = viewport.height * aspectNumerator / aspectDenominator;
2174                viewport.x += (viewport.width - w) / 2;
2175                viewport.width = w;
2176            }
2177            else {
2178                /* letter box */
2179                unsigned h = viewport.width * aspectDenominator / aspectNumerator;
2180                viewport.y += (viewport.height - h) / 2;
2181                viewport.height = h;
2182            }
2183        }
2184        pWindowSettings->contentMode = NEXUS_VideoWindowContentMode_eFull;
2185        break;
2186    case NEXUS_VideoWindowContentMode_eZoom:
2187        if (!sourceAr) {
2188            return BERR_TRACE(NEXUS_INVALID_PARAMETER);
2189        }
2190
2191        /* if display and source ARs are equal, no adjustment required */
2192        if(displayAr != sourceAr)
2193        {
2194            if (displayAr > sourceAr) {
2195                /* vertical clipping - convert to height/width, then do the 1/100ths based math */
2196                verticalClipping += (100 * 100 / sourceAr) - (100 * 100 / displayAr);
2197            }
2198            else {
2199                /* horizontal clipping - units of sourceAr & displayAr are ready for direct math */
2200                horizontalClipping += sourceAr - displayAr;
2201            }
2202        }
2203        pWindowSettings->contentMode = NEXUS_VideoWindowContentMode_eFull;
2204        break;
2205    case NEXUS_VideoWindowContentMode_eFull:
2206        pWindowSettings->contentMode = NEXUS_VideoWindowContentMode_eFull;
2207        break;
2208    case NEXUS_VideoWindowContentMode_eFullNonLinear:
2209    case NEXUS_VideoWindowContentMode_ePanScan:
2210    case NEXUS_VideoWindowContentMode_ePanScanWithoutCorrection:
2211        /* only auto a/r correction supported for these modes */
2212        return BERR_TRACE(NEXUS_NOT_SUPPORTED);
2213    default:
2214        /* invalid value */
2215        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
2216    }
2217
2218
2219    /* use display coordinates as clipBase */
2220    pWindowSettings->clipBase.x = 0; /* unused */
2221    pWindowSettings->clipBase.y = 0; /* unused */
2222    pWindowSettings->clipBase.width = pPosition->displayWidth;
2223    pWindowSettings->clipBase.height = pPosition->displayHeight;
2224
2225    /* start off with no clipping */
2226    pWindowSettings->clipRect = pWindowSettings->clipBase;
2227
2228    /* apply user's clipping */
2229    clip = pWindowSettings->clipBase.width * horizontalClipping / 10000;
2230    pWindowSettings->clipRect.x += clip/2;
2231    pWindowSettings->clipRect.width -= clip;
2232    clip = pWindowSettings->clipBase.height * verticalClipping / 10000;
2233    pWindowSettings->clipRect.y += clip/2;
2234    pWindowSettings->clipRect.height -= clip;
2235
2236    /* apply h/v position while maintaining the viewport and not changing scaling.
2237    let x/y go negative for now. */
2238    pWindowSettings->clipRect.x -= pPosition->horizontalPosition;
2239    pWindowSettings->clipRect.y -= pPosition->verticalPosition;
2240
2241    /* convert viewport to window position, making adjustments to clipping as needed */
2242    pWindowSettings->position = viewport;
2243
2244    /* check if offscreen */
2245    if (viewport.x >= (int)pPosition->displayWidth ||
2246        viewport.x + viewport.width <= 0 ||
2247        viewport.y >= (int)pPosition->displayHeight ||
2248        viewport.y + viewport.height <= 0)
2249    {
2250        pWindowSettings->position = pWindowSettings->clipRect = pWindowSettings->clipBase;
2251        pWindowSettings->position.width = pWindowSettings->position.height = 0;
2252    }
2253    else {
2254        if (viewport.x < 0) {
2255            int temp;
2256            pWindowSettings->position.x = 0;
2257            pWindowSettings->position.width += viewport.x;
2258
2259            temp = (-viewport.x) * pWindowSettings->clipBase.width / viewport.width;
2260            pWindowSettings->clipRect.x += temp;
2261            pWindowSettings->clipRect.width -= temp;
2262        }
2263        if (viewport.y < 0) {
2264            int temp;
2265            pWindowSettings->position.y = 0;
2266            pWindowSettings->position.height += viewport.y;
2267
2268            temp = (-viewport.y) * pWindowSettings->clipBase.height / viewport.height;
2269            pWindowSettings->clipRect.y += temp;
2270            pWindowSettings->clipRect.height -= temp;
2271        }
2272        if (viewport.x + viewport.width > (int)pPosition->displayWidth) {
2273            pWindowSettings->position.width -= viewport.x + viewport.width - pPosition->displayWidth;
2274            pWindowSettings->clipRect.width -= (viewport.width - pWindowSettings->position.width) * pWindowSettings->clipBase.width / viewport.width;
2275        }
2276        if (viewport.y + viewport.height > (int)pPosition->displayHeight) {
2277            pWindowSettings->position.height -= viewport.y + viewport.height - pPosition->displayHeight;
2278            pWindowSettings->clipRect.height -= (viewport.height - pWindowSettings->position.height) * pWindowSettings->clipBase.height / viewport.height;
2279        }
2280    }
2281
2282    BDBG_MSG_TRACE(("NEXUS_CalculateVideoWindowPosition %d,%d,%d,%d; %d,%d,%d,%d; %d,%d,%d,%d",
2283        pWindowSettings->position.x, pWindowSettings->position.y, pWindowSettings->position.width, pWindowSettings->position.height,
2284        pWindowSettings->clipRect.x, pWindowSettings->clipRect.y, pWindowSettings->clipRect.width, pWindowSettings->clipRect.height,
2285        pWindowSettings->clipBase.x, pWindowSettings->clipBase.y, pWindowSettings->clipBase.width, pWindowSettings->clipBase.height));
2286    /* verify that our math is right */
2287    BDBG_ASSERT(pWindowSettings->position.x >= 0);
2288    BDBG_ASSERT(pWindowSettings->position.y >= 0);
2289    BDBG_ASSERT(pWindowSettings->position.width <= pPosition->displayWidth);
2290    BDBG_ASSERT(pWindowSettings->position.height <= pPosition->displayHeight);
2291
2292    return 0;
2293}
2294
2295void NEXUS_VideoWindow_P_InitState(NEXUS_VideoWindowHandle window, unsigned index, NEXUS_DisplayHandle display)
2296{
2297    BKNI_Memset(window, 0, sizeof(*window));
2298    BDBG_OBJECT_SET(window, NEXUS_VideoWindow);
2299    window->open = false;
2300    window->display = display;
2301    window->adjContext.stMadSettings.enable32Pulldown = true;
2302    window->adjContext.stMadSettings.pixelFormat = NEXUS_PixelFormat_eUnknown; /* eUnknown allows VDB to set the optimal format */
2303    window->adjContext.stAnrSettings.pixelFormat = NEXUS_PixelFormat_eUnknown; /* eUnknown allows VDB to set the optimal format */
2304    /* default to bypassing filtering. Disabling and Enabling causes flashes, but enabling and bypassing does not*/
2305    window->adjContext.stAnrSettings.anr.mode = NEXUS_VideoWindowFilterMode_eBypass;
2306    window->adjContext.stAnrSettings.anr.level = -(BVDC_QP_ADJUST_STEPS-1); /* minimum filter value*/
2307    window->adjContext.stDnrSettings.bnr.mode = NEXUS_VideoWindowFilterMode_eBypass;
2308    window->adjContext.stDnrSettings.bnr.level = -(BVDC_QP_ADJUST_STEPS-1);
2309    window->adjContext.stDnrSettings.dcr.mode = NEXUS_VideoWindowFilterMode_eBypass;
2310    window->adjContext.stDnrSettings.dcr.level =  -(BVDC_QP_ADJUST_STEPS-1);
2311    window->adjContext.stDnrSettings.mnr.mode = NEXUS_VideoWindowFilterMode_eBypass;
2312    window->adjContext.stDnrSettings.mnr.level = -(BVDC_QP_ADJUST_STEPS-1);
2313    window->adjContext.stSclSettings.horizontalLumaDeringing = true;
2314    window->adjContext.stSclSettings.verticalLumaDeringing = true;
2315    window->adjContext.stSclSettings.horizontalChromaDeringing = true;
2316    window->adjContext.stSclSettings.verticalChromaDeringing = true;
2317#ifdef NEXUS_DYNAMIC_BACKLIGHT_SCALE_FACTOR
2318    window->picContext.stCustomContrast.dynamicBacklightScaleFactor = NEXUS_DYNAMIC_BACKLIGHT_SCALE_FACTOR; /* full scaling */
2319#endif
2320    window->cfg.autoMaster = (index == 0);
2321    window->cfg.alpha = 0xFF;
2322    window->cfg.contentMode =  NEXUS_VideoWindowContentMode_eFull;
2323    window->cfg.sourceBlendFactor = NEXUS_CompositorBlendFactor_eSourceAlpha;
2324    window->cfg.destBlendFactor = NEXUS_CompositorBlendFactor_eInverseSourceAlpha;
2325    window->cfg.constantAlpha = 0xFF;
2326    window->cfg.visible = true;
2327    window->cfg.zorder = index;
2328    window->cfg.scaleFactorRounding.enabled = true;
2329    window->cfg.scaleFactorRounding.horizontalTolerance = 0;
2330#if NEXUS_CRC_CAPTURE
2331    window->cfg.scaleFactorRounding.verticalTolerance = 0;
2332#else
2333    window->cfg.scaleFactorRounding.verticalTolerance = 3;
2334#endif
2335
2336    BKNI_Memcpy(&window->picContext.stCustomContrast.dcTable1[0], &alDCTable1[0], sizeof(window->picContext.stCustomContrast.dcTable1));
2337    BKNI_Memcpy(&window->picContext.stCustomContrast.dcTable2[0], &alDCTable1[0], sizeof(window->picContext.stCustomContrast.dcTable2));
2338    BKNI_Memcpy(&window->picContext.stCustomContrast.ireTable[0], &aIreTable[0], sizeof(window->picContext.stCustomContrast.ireTable));
2339
2340    /* We default forceCapture on for set-tops because it's usually needed for HD/SD VEC sync and all usage modes allow it.
2341    We don't default forceCapture on for DTV because it can't be used in some usage modes. */
2342    window->cfg.forceCapture = true;
2343#if NEXUS_NUM_MOSAIC_DECODES
2344    window->mosaic.mosaicSettings.backendMosaic.clipRect.width = 1920;
2345    window->mosaic.mosaicSettings.backendMosaic.clipRect.width = 1080;
2346    window->mosaic.mosaicSettings.backendMosaic.clipBase = window->mosaic.mosaicSettings.backendMosaic.clipRect;
2347#endif
2348}
2349
2350void NEXUS_VideoWindow_GetAfdSettings( NEXUS_VideoWindowHandle window, NEXUS_VideoWindowAfdSettings *pSettings )
2351{
2352    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
2353    *pSettings = window->afdSettings;
2354}
2355
2356NEXUS_Error NEXUS_VideoWindow_SetAfdSettings( NEXUS_VideoWindowHandle window, const NEXUS_VideoWindowAfdSettings *pSettings )
2357{
2358    BDBG_OBJECT_ASSERT(window, NEXUS_VideoWindow);
2359
2360    window->afdSettings = *pSettings;
2361    window->afdSet = true;
2362
2363#ifndef B_HAS_LEGACY_VDC
2364    if (window->vdcState.window) {
2365        BERR_Code rc;
2366
2367        BDBG_CASSERT(NEXUS_AfdMode_eUser == (NEXUS_AfdMode)BVDC_AfdMode_eUser);
2368        BDBG_CASSERT(NEXUS_AfdClip_eOptionalLevel2 == (NEXUS_AfdClip)BVDC_AfdClip_eOptionalLevel2);
2369        BDBG_CASSERT(sizeof(NEXUS_VideoWindowAfdSettings) == sizeof(BVDC_AfdSettings));
2370        rc = BVDC_Window_SetAfdSettings(window->vdcState.window, (const BVDC_AfdSettings *)(const NEXUS_VideoWindowAfdSettings *)&window->afdSettings);
2371        if (rc) return BERR_TRACE(rc);
2372
2373        rc = NEXUS_Display_P_ApplyChanges();
2374        if (rc) return BERR_TRACE(rc);
2375    }
2376#endif
2377
2378    return 0;
2379}
2380
2381/**
2382set this window's "SetMasterFrameRate" setting.
2383if true, we may need to set another window false. if false, we may need to set another window true.
2384this function must be called from all places in nexus where these conditions may change.
2385**/
2386NEXUS_Error NEXUS_VideoWindow_P_ConfigMasterFrameRate(NEXUS_VideoWindowHandle window, const NEXUS_DisplaySettings *pDisplaySettings, const NEXUS_VideoWindowSettings *pWindowsettings)
2387{
2388    BERR_Code rc;
2389    bool masterFrameRate;
2390
2391    /* pDisplaySettings->frameRateMaster takes precedence */
2392    masterFrameRate = (pDisplaySettings->frameRateMaster ? pDisplaySettings->frameRateMaster == window->input : pWindowsettings->autoMaster);
2393
2394    /* if vdc window destroyed, we can throw SetMasterFrameRate to the other window as well */
2395    masterFrameRate = masterFrameRate && window->vdcState.window;
2396
2397#if 0
2398    /* TODO: masterFrameRate could be forced false if this window is not sync-locked. but that info is currently not available immediately after window creation. */
2399    if (masterFrameRate) {
2400        BVDC_Window_Status vdcStatus;
2401        rc = BVDC_Window_GetStatus(window->vdcState.window, &vdcStatus);
2402        if (rc) return BERR_TRACE(rc);
2403        masterFrameRate = masterFrameRate && vdcStatus.bSyncLock;
2404        BDBG_MSG_TRACE(("synclock %d", vdcStatus.bSyncLock));
2405    }
2406#endif
2407
2408    BDBG_MSG_TRACE(("setting SetMasterFrameRate(%d, %d -> %d) based on %d %d %d", window->index, window->vdcState.masterFrameRate, masterFrameRate,
2409        pDisplaySettings->frameRateMaster, pWindowsettings->autoMaster, window->vdcState.window));
2410
2411    if (masterFrameRate != window->vdcState.masterFrameRate) {
2412#if NEXUS_NUM_VIDEO_WINDOWS > 1
2413        NEXUS_VideoWindowHandle otherWindow = NULL;
2414
2415        /* only one window per display can have SetMasterFrameRate(true). main overrides pip. */
2416        otherWindow = &window->display->windows[1 - window->index];
2417        if (!otherWindow->open) otherWindow = NULL;
2418#endif
2419
2420        if (masterFrameRate) {
2421            /* find any conflict and turn off SetMasterFrameRate on another window */
2422#if NEXUS_NUM_VIDEO_WINDOWS > 1
2423            if (otherWindow && otherWindow->vdcState.window && otherWindow->vdcState.masterFrameRate) {
2424                if (otherWindow->index == 1) {
2425                    rc = BVDC_Window_SetMasterFrameRate(otherWindow->vdcState.window, false);
2426                    if (rc) return BERR_TRACE(rc);
2427                    otherWindow->vdcState.masterFrameRate = false;
2428                }
2429                else {
2430                    /* don't allow pip to override main */
2431                    masterFrameRate = false;
2432                }
2433            }
2434#endif
2435
2436            rc = BVDC_Window_SetMasterFrameRate(window->vdcState.window, masterFrameRate);
2437            if (rc) return BERR_TRACE(rc);
2438        }
2439        else {
2440            if (window->vdcState.window) {
2441                rc = BVDC_Window_SetMasterFrameRate(window->vdcState.window, false);
2442                if (rc) return BERR_TRACE(rc);
2443            }
2444
2445            /* throw SetMasterFrameRate to other window if it wants it. it's ok if it's sync-slip. */
2446#if NEXUS_NUM_VIDEO_WINDOWS > 1
2447            if (otherWindow && otherWindow->vdcState.window && otherWindow->cfg.autoMaster && !otherWindow->vdcState.masterFrameRate) {
2448                rc = BVDC_Window_SetMasterFrameRate(otherWindow->vdcState.window, true);
2449                if (rc) return BERR_TRACE(rc);
2450                otherWindow->vdcState.masterFrameRate = true;
2451            }
2452#endif
2453        }
2454        window->vdcState.masterFrameRate = masterFrameRate;
2455    }
2456    return 0;
2457}
2458
2459NEXUS_Error NEXUS_VideoWindow_SetSettings_priv( NEXUS_VideoWindowHandle handle, const NEXUS_VideoWindowSettings *pSettings )
2460{
2461    NEXUS_ASSERT_MODULE();
2462    /* call _impl version */
2463    return NEXUS_VideoWindow_SetSettings(handle, pSettings);
2464}
Note: See TracBrowser for help on using the repository browser.