source: svn/newcon3bcm2_21bu/BSEAV/api/src/nexus/bsettop_graphics.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: 49.1 KB
Line 
1/***************************************************************************
2 *  Copyright (c) 2003-2010, Broadcom Corporation
3 *  All Rights Reserved
4 *  Confidential Property of Broadcom Corporation
5 *
6 * THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 * AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR
8 * EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: bsettop_graphics.c $
11 * $brcm_Revision: 47 $
12 * $brcm_Date: 7/14/10 12:48p $
13 *
14 * Module Description:
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /BSEAV/api/src/nexus/bsettop_graphics.c $
19 *
20 * 47   7/14/10 12:48p erickson
21 * SW7405-3787: fix alignment units
22 *
23 * 46   4/4/10 8:07a agin
24 * SWNOOS-402:  Fix SDE compiler error.
25 *
26 * 45   3/1/10 10:56a erickson
27 * SW7550-272: add bgraphics_pixel_format_a8_y8_cb8_cr8
28 *
29 * 44   2/11/10 2:37p erickson
30 * SW7405-3903: use NEXUS_Graphics2D_Checkpoint correctly
31 *
32 * 43   1/18/10 3:07p erickson
33 * SW7405-3787: default settop api surface allocations to 4K alignment to
34 * avoid stale data in the RAC
35 *
36 * 42   12/11/09 4:30p mphillip
37 * SW7550-112: Merge 7550 changes to main branch
38 *
39 * Refsw_7550/6   12/11/09 2:25p rjain
40 * SW7550-112: Merging LATEST FROM  main branch.
41 *
42 * Refsw_7550/5   11/25/09 3:35p chengli
43 * SW7550-64: remove compile warning
44 *
45 * Refsw_7550/4   11/18/09 8:29p chengli
46 * SW7550-64 : GFD of 7550 should do the vertical scaling
47 *
48 * 41   11/10/09 1:42p nickh
49 * SW7420-166:  Add support for 3rd display and DUAL_OUTPUT
50 *
51 * Refsw_7550/3   11/5/09 11:25a nitinb
52 * sw7550-64: Initial brutus build for 7550
53 *
54 * 40   9/30/09 10:38a erickson
55 * SW7405-3106: don't overwrite user's bsurface_settings.position for
56 * framebuffers. only update the cliprect.
57 *
58 * 39   8/19/09 11:34a mphillip
59 * PR57626: Add zorder support to shim
60 *
61 * 38   8/14/09 3:10p erickson
62 * PR55994: allow for default NULL rect
63 *
64 * 37   7/10/09 2:41p agin
65 * PR56698: Fix graphics test for no-os.
66 *
67 * 36   6/5/09 2:07p vishk
68 * PR 55748: (NEXUS) Clipping problem with bsettop Nexus shim
69 *
70 * 35   4/17/09 9:25a erickson
71 * PR54270: fix non-7420
72 *
73 * 34   4/16/09 4:42p erickson
74 * PR54270: use GFD vertical upscale in 7420 brutus
75 *
76 * 33   4/2/09 3:22p erickson
77 * PR53698: implement some (not all) of the bsurface_blit operations
78 *
79 * 32   2/26/09 1:26p erickson
80 * PR52363: bsurface_get_display should create a single-buffered
81 * framebuffer to be backward compatible
82 *
83 * 31   2/20/09 3:58p erickson
84 * PR52363: initialize memory in bgraphics_create_framebuffer
85 *
86 * 30   1/5/09 10:33a erickson
87 * PR49688: downgrade ERR to MSG
88 *
89 * 29   1/2/09 6:01p katrep
90 * PR49688: Updated bgraphics_flip and bgraphics_flip_sync
91 *
92 * 28   8/21/08 4:15p vishk
93 * PR 45550: Invoking graphics results in loss of decode video.
94 *
95 * 27   8/19/08 4:38p erickson
96 * PR45866: add NEXUS_Graphics2DOpenSettings
97 *
98 * 26   8/5/08 2:59p erickson
99 * PR44958: bsurface_create should implicitly create fb if needed
100 * (backward compatible)
101 *
102 * 25   6/26/08 1:35p jgarrett
103 * PR 36285: Updating blit to match new api spec
104 *
105 * 24   6/18/08 10:13p erickson
106 * PR36068: don't create a fb on first bgraphics_set call
107 *
108 * 23   5/5/08 3:50p erickson
109 * PR36068: set graphics colorkey
110 *
111 * 22   4/15/08 4:01p erickson
112 * PR41718: don't use FastBlit unless we properly screen out all
113 * exceptions
114 *
115 * 21   4/14/08 3:15p erickson
116 * PR41738: use FastBlit when able
117 *
118 * 20   4/10/08 9:56a erickson
119 * PR36068: coverity fixes
120 *
121 * 19   4/3/08 5:41p jgarrett
122 * PR 41312: Revising callback logic
123 *
124 * 18   3/19/08 9:23p erickson
125 * PR36068: convert bgraphics.surfaces to lst
126 *
127 * 17   2/25/08 9:23a erickson
128 * PR36068: impl more functions
129 *
130 * 16   1/7/08 10:15a erickson
131 * PR36068: close graphics
132 *
133 * 15   12/4/07 10:12a erickson
134 * PR36068: fix double-buffered framebuffer support
135 *
136 * 14   12/3/07 4:58p erickson
137 * PR36068: use B_N_GRC to limit number of Graphics2D interfaces opened
138 *
139 * 13   11/27/07 1:44p erickson
140 * PR37590: added BDBG_OBJECT code
141 *
142 * 12   11/14/07 3:23p erickson
143 * PR36068: must flush surfaces before calling NEXUS_Graphics2D fill or
144 * blit
145 *
146 * 11   11/14/07 2:21p erickson
147 * PR36068: fix compile error
148 *
149 * 10   11/14/07 1:28p erickson
150 * PR36068: convert to cpu-based blit/fill until Nexus fill problems
151 * debugged
152 *
153 * 9   11/12/07 3:57p erickson
154 * PR36068: update
155 *
156 * 8   11/12/07 2:34p erickson
157 * PR36068: update
158 *
159 * 7   11/2/07 1:25p erickson
160 * PR36633: update nexus enums
161 *
162 * 6   10/19/07 12:26p erickson
163 * PR36068: added blitter
164 *
165 * 5   10/17/07 10:09a erickson
166 * PR36068: default and check destination/source width/height
167 *
168 * 4   10/17/07 9:45a erickson
169 * PR36068: there should be one bsurface_settings for framebuffers
170 *
171 * 3   10/16/07 1:17p erickson
172 * PR36068: update
173 *
174 * 2   10/16/07 12:35p erickson
175 * PR36068: brutus up over settop api/nexus
176 *
177 * 1   10/15/07 2:36p erickson
178 * PR36068: initial
179 *
180 ***************************************************************************/
181#include "bsettop_impl.h"
182
183BDBG_MODULE(graphics);
184
185BDBG_OBJECT_ID(bgraphics);
186BDBG_OBJECT_ID(bsurface);
187
188struct bgraphics g_graphics[B_N_GRAPHICS];
189static int g_refCount=0;
190static B_MutexHandle g_checkpointMutex;
191
192#define COPY_RECT(pNexus, pSettop) \
193    do { \
194        if (pSettop) { \
195            (pNexus)->x = (pSettop)->x; \
196            (pNexus)->y = (pSettop)->y; \
197            (pNexus)->width = (pSettop)->width; \
198            (pNexus)->height = (pSettop)->height; \
199        } \
200        else {(pNexus)->width = (pNexus)->height = 0;} \
201    } while (0)
202
203/**
204Meta-data for each pixel format.
205This structure must be kept up-to-date with order of enum.
206**/
207struct pixel_format_info {
208    bgraphics_pixel_format pixel_format;
209    bool rgb;
210    bool palette; /* NOTE: All palettes are RGB. */
211    bool alpha_per_pixel;
212    int bpp; /* bits per pixel */
213} g_pixel_format_info[] = {
214    {bgraphics_pixel_format_r5_g6_b5, true, false, false, 16},
215    {bgraphics_pixel_format_a1_r5_g5_b5, true, false, true, 16},
216    {bgraphics_pixel_format_r5_g5_b5_a1, true, false, true, 16},
217    {bgraphics_pixel_format_a4_r4_g4_b4, true, false, true, 16},
218    {bgraphics_pixel_format_r4_g4_b4_a4, true, false, true, 16},
219    {bgraphics_pixel_format_a8_r8_g8_b8, true, false, true, 32},
220    {bgraphics_pixel_format_palette8, true, true, false, 8},
221    {bgraphics_pixel_format_a8_palette8, true, true, true, 16},
222    {bgraphics_pixel_format_a0, false, false, false, 0},
223    {bgraphics_pixel_format_a8, true, false, true, 8},
224    {bgraphics_pixel_format_y08_cb8_y18_cr8, false, false, false, 32},
225    {bgraphics_pixel_format_cr8_y18_cb8_y08, false, false, false, 32},
226    {bgraphics_pixel_format_cr8_y18_cb8_y08, false, false, false, 32},
227    {bgraphics_pixel_format_video_tunnel, false, false, false, 0},
228    {bgraphics_pixel_format_palette2, true, true, false, 2},
229    {bgraphics_pixel_format_palette4, true, true, false, 4}
230};
231
232#if BCHP_CHIP == 7550
233/* Color-Conversion Matrices for 7550. 7550 GFD1 doesn't have
234   color conversion capability. */
235/*
236ITU-R BT.601:
237        Y  =  (0.257 * R) + (0.504 * G) + (0.098 * B) + 16
238        Cb = -(0.148 * R) - (0.291 * G) + (0.439 * B) + 128
239        Cr =  (0.439 * R) - (0.368 * G) - (0.071 * B) + 128
240*/
241static int32_t g_ai32_Matrix_RGBtoYCbCr_BT_601[20] =
242{
243    (int32_t) ( 0.257f * (1 << 8)),   /*  R factor for Y */
244    (int32_t) ( 0.504f * (1 << 8)),   /*  G factor for Y */
245    (int32_t) ( 0.098f * (1 << 8)),   /*  B factor for Y */
246    (int32_t) 0,                      /*  A factor for Y */
247    (int32_t) (16 * (1 << 8)),        /* Increment for Y */
248    (int32_t) (-0.148f * (1 << 8)),   /*  R factor for Cb */
249    (int32_t) (-0.291f * (1 << 8)),   /*  G factor for Cb */
250    (int32_t) ( 0.439f * (1 << 8)),   /*  B factor for Cb */
251    (int32_t) 0,                      /*  A factor for Cb */
252    (int32_t) (128 * (1 << 8)),      /* Increment for Cb */
253    (int32_t) ( 0.439f * (1 << 8)),   /*  R factor for Cr */
254    (int32_t) (-0.368f * (1 << 8)),   /*  G factor for Cr */
255    (int32_t) (-0.071f * (1 << 8)),   /*  B factor for Cr */
256    (int32_t) 0,                      /*  A factor for Cr */
257    (int32_t) (128 * (1 << 8)),       /* Increment for Cr */
258    (int32_t) 0,                      /*  R factor for A */
259    (int32_t) 0,                      /*  G factor for A */
260    (int32_t) 0,                      /*  B factor for A */
261    (int32_t) (1 << 8),               /*  A factor for A */
262    (int32_t) 0,                      /* Increment for A */
263};
264
265/*
266ITU-R BT.709:
267        Y  =  (0.183 * R) + (0.614 * G) + (0.062 * B) + 16
268        Cb = -(0.101 * R) - (0.339 * G) + (0.439 * B) + 128
269        Cr =  (0.439 * R) - (0.339 * G) - (0.040 * B) + 128
270*/
271static int32_t g_ai32_Matrix_RGBtoYCbCr_BT_709[20] =
272{
273    (int32_t) ( 0.183f * (1 << 8)),   /*  R factor for Y */
274    (int32_t) ( 0.614f * (1 << 8)),   /*  G factor for Y */
275    (int32_t) ( 0.062f * (1 << 8)),   /*  B factor for Y */
276    (int32_t) 0,                      /*  A factor for Y */
277    (int32_t) (16 * (1 << 8)),        /* Increment for Y */
278    (int32_t) (-0.101f * (1 << 8)),   /*  R factor for Cb */
279    (int32_t) (-0.339f * (1 << 8)),   /*  G factor for Cb */
280    (int32_t) ( 0.439f * (1 << 8)),   /*  B factor for Cb */
281    (int32_t) 0,                      /*  A factor for Cb */
282    (int32_t) (128 * (1 << 8)),       /* Increment for Cb */
283    (int32_t) ( 0.439f * (1 << 8)),   /*  R factor for Cr */
284    (int32_t) (-0.339f * (1 << 8)),   /*  G factor for Cr */
285    (int32_t) (-0.040f * (1 << 8)),   /*  B factor for Cr */
286    (int32_t) 0,                      /*  A factor for Cr */
287    (int32_t) (128 * (1 << 8)),       /* Increment for Cr */
288    (int32_t) 0,                      /*  R factor for A */
289    (int32_t) 0,                      /*  G factor for A */
290    (int32_t) 0,                      /*  B factor for A */
291    (int32_t) (1 << 8),               /*  A factor for A */
292    (int32_t) 0,                      /* Increment for A */
293};
294
295#endif
296
297#if B_N_GRC
298static void bgraphics_p_checkpoint_callback(void *data, int unused)
299{
300    bgraphics_t graphics = (bgraphics_t)data;
301    BSTD_UNUSED(unused);
302    BKNI_SetEvent(graphics->gEvent);
303}
304
305static void bgraphics_p_checkpoint(bgraphics_t graphics)
306{
307#ifdef NO_OS
308    BSTD_UNUSED(graphics);
309    BKNI_Sleep(30);
310#else
311
312    BERR_Code errCode;
313
314    b_unlock();
315    B_Mutex_Lock(g_checkpointMutex);
316    /* Unlock to avoid overflow when UI is busy */
317    errCode = NEXUS_Graphics2D_Checkpoint(graphics->graphics2d, NULL);
318    if (errCode == NEXUS_GRAPHICS2D_QUEUED) {
319        errCode = BKNI_WaitForEvent(graphics->gEvent, 5000);
320    }
321    B_Mutex_Unlock(g_checkpointMutex);
322    b_lock();
323    if ( errCode )
324    {
325        BDBG_ERR(("Graphics Checkpoint Timeout"));
326    }
327#endif
328}
329#endif
330
331bgraphics_t bgraphics_open(bobject_t id, bdisplay_t display)
332{
333    unsigned index = B_ID_GET_INDEX(id);
334    bgraphics_t graphics;
335
336    if (index >= B_N_GRAPHICS) {
337        BSETTOP_ERROR(berr_not_available);
338        return NULL;
339    }
340    graphics = &g_graphics[index];
341    BDBG_OBJECT_SET(graphics, bgraphics);
342    graphics->index = index;
343    if (graphics->display || !display || display->graphics) {
344        BSETTOP_ERROR(berr_not_available);
345        return NULL;
346    }
347
348#if B_N_GRC
349    if (index >= B_N_GRC) {
350        /* This assumes the other bgraphics was created first */
351        graphics->graphics2d = g_graphics[index % B_N_GRC].graphics2d;
352        graphics->gEvent = g_graphics[index % B_N_GRC].gEvent;
353    }
354    else {
355        BKNI_CreateEvent(&graphics->gEvent);
356        graphics->graphics2d = NEXUS_Graphics2D_Open(index, NULL);
357    }
358    if (!graphics->graphics2d) {
359        BSETTOP_ERROR(berr_not_available);
360        return NULL;
361    }
362
363    {
364        NEXUS_Graphics2DSettings settings;
365        NEXUS_Error rc;
366
367        NEXUS_Graphics2D_GetSettings(graphics->graphics2d, &settings);
368        settings.checkpointCallback.callback = bgraphics_p_checkpoint_callback;
369        settings.checkpointCallback.context = graphics;
370        rc = NEXUS_Graphics2D_SetSettings(graphics->graphics2d, &settings);
371        if (rc) {
372            NEXUS_Graphics2D_Close(graphics->graphics2d);
373            graphics->graphics2d = NULL;
374            BSETTOP_ERROR(berr_not_available);
375            return NULL;
376        }
377    }
378#endif
379
380    graphics->display = display;
381    display->graphics = graphics;
382    graphics->settings.destination_width = 720;
383    graphics->settings.destination_height = 480;
384    graphics->settings.source_width = 720;
385    graphics->settings.source_height = 480;
386    graphics->settings.enabled = true;
387    graphics->settings.chromakey_enabled = true;
388    BLST_Q_INIT(&graphics->surfaces);
389
390    if ( 0 == g_refCount++ )
391    {
392        g_checkpointMutex = B_Mutex_Create(NULL);
393        BDBG_ASSERT(NULL != g_checkpointMutex);
394    }
395
396    return graphics;
397}
398
399void bgraphics_close(bgraphics_t graphics)
400{
401    unsigned i;
402    NEXUS_GraphicsSettings graphicsSettings;
403
404    NEXUS_Display_GetGraphicsSettings(graphics->display->nDisplay, &graphicsSettings);
405    graphicsSettings.enabled = false;
406    NEXUS_Display_SetGraphicsSettings(graphics->display->nDisplay, &graphicsSettings);
407
408    graphics->closing = true;
409
410    for (i=0;i<MAX_GRAPHICS_FBS;i++) {
411        if (graphics->fb[i]) {
412            bsurface_destroy(graphics->fb[i]);
413            graphics->fb[i] = NULL;
414        }
415    }
416    graphics->display->graphics = NULL;
417    graphics->display = NULL;
418#if B_N_GRC
419    /* This assumes the app closes bgraphics in reverse order. */
420    if (graphics->index < B_N_GRC) {
421        NEXUS_Graphics2D_Close(graphics->graphics2d);
422        BKNI_DestroyEvent(graphics->gEvent);
423    }
424#endif
425    BDBG_OBJECT_UNSET(graphics, bgraphics);
426
427    if ( 0 == --g_refCount )
428    {
429        B_Mutex_Destroy(g_checkpointMutex);
430        g_checkpointMutex = NULL;
431    }
432}
433
434/**
435bgraphics_p_used_framebuffer determines the actual width of the framebuffer
436that will be used. This results in horizontal upscaling if needed.
437
438If you must handle all output formats, we recommend that you create a
439framebuffer that is 1280x1080. Three main cases result:
440
441case 1) 1080i output
442Because integer scales are preferred, the used portion of the framebuffer will
443be 960. If you're using a 720x480 offscreen surface, you'll have two
444upscales, one with GRC and other with CMP (720->960->1080).
445
446case 2) 480i output
447If your framebuffer is 960 wide and destination width is 720, clip = 240 and
448there's no upscale.
449
450case 3) 720p output
451You will use the entire framebuffer.
452If you're using a 720x480 offscreen surface, you'll have one upscale with the
453GRC (720->1280->1280).
454**/
455static void bgraphics_p_used_framebuffer(bgraphics_t g,
456    const bgraphics_settings *settings, uint16_t *pWidth, uint16_t *pHeight)
457{
458    bsurface_t fb = g->fb[g->cur_fb];
459    BDBG_ASSERT(fb);
460
461    if (!settings)
462        settings = &g->settings;
463
464    if( fb->settings.position.width >= settings->destination_width ) {
465        /* No CMP scaling required */
466        *pWidth = settings->destination_width;
467    }
468    else {
469        *pWidth = fb->settings.position.width;
470    }
471
472#if BCHP_CHIP != 7420 && BCHP_CHIP != 7550
473    *pHeight = g->settings.destination_height;
474#else
475    if( fb->settings.position.height >= g->settings.destination_height ) {
476        /* No CMP scaling required */
477        *pHeight = g->settings.destination_height;
478    }
479    else {
480        *pHeight = fb->settings.position.height;
481    }
482#endif
483}
484
485static bresult bgraphics_p_set_framebuffer(bgraphics_t graphics)
486{
487    NEXUS_Error rc;
488    NEXUS_GraphicsSettings graphicsSettings;
489    bsurface_t fb;
490    unsigned i;
491
492    BDBG_OBJECT_ASSERT(graphics, bgraphics);
493
494    fb = graphics->fb[graphics->cur_fb]; /* the current */
495    if (!fb) return BSETTOP_ERROR(berr_not_available);
496
497    bsurface_sync(fb);
498
499    /* only use fb[0] for settings */
500    BDBG_OBJECT_ASSERT(graphics->display, bdisplay);
501    NEXUS_Display_GetGraphicsSettings(graphics->display->nDisplay, &graphicsSettings);
502    graphicsSettings.enabled = graphics->settings.enabled;
503    graphicsSettings.alpha = fb->settings.alpha;
504    graphicsSettings.position.width = graphics->settings.destination_width;
505    graphicsSettings.position.height = graphics->settings.destination_height;
506    graphicsSettings.chromakeyEnabled = graphics->settings.chromakey_enabled;
507    graphicsSettings.lowerChromakey = graphics->settings.lower_chromakey;
508    graphicsSettings.upperChromakey = graphics->settings.upper_chromakey;
509
510    /* calc framebuffer cliprect based on display format */
511    bgraphics_p_used_framebuffer(graphics, &graphics->settings, &graphicsSettings.clip.width, &graphicsSettings.clip.height);
512
513    /* apply cliprect update to all framebuffer surfaces */
514    for (i=0;i<graphics->num_fbs;i++) {
515        graphics->fb[i]->settings.cliprect.width = graphicsSettings.clip.width;
516        graphics->fb[i]->settings.cliprect.height = graphicsSettings.clip.height;
517    }
518
519    BDBG_MSG(("fb position %dx%d, clip %dx%d, enabled=%d",
520        graphicsSettings.position.width, graphicsSettings.position.height,
521        graphicsSettings.clip.width, graphicsSettings.clip.height,
522        graphics->settings.enabled));
523
524    rc = NEXUS_Display_SetGraphicsSettings(graphics->display->nDisplay, &graphicsSettings);
525    if (rc) return BSETTOP_ERROR(berr_external_error);
526
527    rc = NEXUS_Display_SetGraphicsFramebuffer(graphics->display->nDisplay, fb->nSurface);
528    if (rc) return BSETTOP_ERROR(berr_external_error);
529
530    return 0;
531}
532
533void bgraphics_get(bgraphics_t graphics, bgraphics_settings *settings)
534{
535    *settings = graphics->settings;
536}
537
538bresult bgraphics_set(bgraphics_t graphics, const bgraphics_settings *settings)
539{
540    BDBG_OBJECT_ASSERT(graphics, bgraphics);
541    graphics->settings = *settings;
542    if (graphics->fb[0]) {
543        bgraphics_p_set_framebuffer(graphics);
544        return bgraphics_sync(graphics);
545    }
546    else {
547        return 0;
548    }
549}
550
551static void bgraphics_p_scale_rect(bgraphics_t g, const bsettop_rect *rect, bsettop_rect *destrect)
552{
553    uint16_t dest_width, dest_height;
554
555    /* destrect is calculated using graphics_settings dest==>src ratio. This means we
556    don't support per-surface scaling. But this is typical for UI's and makes
557    display format changes much easier. */
558
559    /* This bit of calculation handles the upscaled framebuffer. It's recalculating
560    what was done in bgraphics_set. */
561    bgraphics_p_used_framebuffer(g, NULL, &dest_width, &dest_height);
562
563    if (g->settings.source_width && g->settings.source_height) {
564        destrect->x = rect->x * dest_width / g->settings.source_width;
565        destrect->y = rect->y * g->settings.destination_height / g->settings.source_height;
566        destrect->width = rect->width * dest_width / g->settings.source_width;
567        destrect->height = rect->height * dest_height / g->settings.source_height;
568    }
569    else {
570        BDBG_ERR(("bgraphics_p_scale_rect failed because of bad source dim %dx%d", g->settings.source_width, g->settings.source_height));
571    }
572}
573
574#define NEXT_FB_INDEX(g) ((g)->cur_fb+1>=(g)->num_fbs?0:(g)->cur_fb+1)
575
576bresult bgraphics_sync(bgraphics_t g)
577{
578    bsurface_t surface, fb;
579    bresult result = b_ok;
580
581    BDBG_OBJECT_ASSERT(g, bgraphics);
582
583    fb = g->fb[NEXT_FB_INDEX(g)]; /* get next framebuffer */
584
585    if (!fb) {
586        return BSETTOP_ERROR(berr_not_available);
587    }
588
589    /* flush cached memory for the framebuffer in case an old CPU write is still in cache */
590    NEXUS_Surface_Flush(fb->nSurface);
591
592    /* If at least one surface is marked visible and if offscreen_framebuffer is not set, clear the framebuffer.
593    After this, we'll redraw all visible surfaces anyway. This takes care of deleting
594    and moving visible surfaces and gives a blank slate if we are going to be blending.
595    All direct draws to the framebuffer are wiped out. */
596    if (!g->settings.offscreen_framebuffer) {
597        for (surface = BLST_Q_FIRST(&g->surfaces);surface;surface=BLST_Q_NEXT(surface, link)) {
598            if (surface->settings.visible)
599                break;
600        }
601        if (surface) {
602            /* Show video through the framebuffer by default. If we don't have alpha per
603            pixel and chromakey isn't enabled, you're going to get black. */
604            bgraphics_pixel color = g->settings.chromakey_enabled ?
605                g->settings.lower_chromakey : 0x00000000;
606            bsurface_fill(g->fb[0], &fb->settings.cliprect, color);
607        }
608    }
609
610    /* Process all visible, non-framebuffer surfaces */
611    for (surface = BLST_Q_FIRST(&g->surfaces);surface;surface=BLST_Q_NEXT(surface, link)) {
612        if (surface->settings.visible) {
613            bsettop_rect destrect, srcrect;
614
615            NEXUS_Surface_Flush(surface->nSurface);
616
617            bgraphics_p_scale_rect(g, &surface->settings.position, &destrect);
618
619            /* take into account cliprect in blit */
620            srcrect.x = surface->settings.cliprect.x;
621            srcrect.y = surface->settings.cliprect.y;
622            srcrect.width = surface->settings.cliprect.width;
623            srcrect.height = surface->settings.cliprect.height;
624            BDBG_MSG(("bgraphics_sync[%d], %d,%d,%d,%d -> %d,%d,%d,%d",
625                g->index,
626                srcrect.x,srcrect.y,srcrect.width,srcrect.height,
627                destrect.x,destrect.y,destrect.width,destrect.height
628                ));
629
630            #if B_N_GRC
631            /* blit to the framebuffer */
632            if ((surface->settings.alpha < 0xFF) || g->settings.offscreen_framebuffer) {
633                /* In this case, we're going to copy surface's alpha channel. We may
634                or may not blend with dest depending on constant alpha. */
635                result = bsurface_blit(fb, &destrect,
636                    BSURFACE_BLEND_WITH_PIXEL1|BSURFACE_SET_DEST_ALPHA_WITH_SRC1_ALPHA,
637                    surface, &srcrect,
638                    fb, &destrect,
639                    surface->settings.alpha, 0);
640            }
641            else {
642                /* In this case, blend surface with dest, both color and alpha channels,
643                using surface's alpha channel. */
644                result = bsurface_blit(fb, &destrect,
645                    BSURFACE_BLEND_WITH_SRC1_ALPHA|BSURFACE_SET_DEST_ALPHA_WITH_AVG_ALPHA,
646                    surface, &srcrect,
647                    fb, &destrect,
648                    0, 0);
649            }
650            #else
651            {
652                result = bsurface_copy(fb, &destrect, surface, &srcrect);
653            }
654            #endif
655            if (result) goto done;
656        }
657    }
658
659
660#if B_N_GRC
661    /* Now wait for all of it to complete */
662    bgraphics_p_checkpoint(g);
663#endif
664
665done:
666    return result;
667}
668
669bresult bsurface_sync(bsurface_t surface)
670{
671    BDBG_OBJECT_ASSERT(surface, bsurface);
672    NEXUS_Surface_Flush(surface->nSurface);
673    if (surface->is_fb) {
674        bgraphics_sync(surface->graphics);
675    }
676    else {
677#if B_N_GRC
678        bgraphics_p_checkpoint(surface->graphics);
679#endif
680    }
681    return 0;
682}
683
684bresult bgraphics_flip(bgraphics_t graphics)
685{
686    bresult result;
687    bsettop_rect rect;
688    bsurface_t fb1, fb2;
689
690    BDBG_OBJECT_ASSERT(graphics, bgraphics);
691    /* always an implicit sync, even if not double or triple buffered */
692    result = bgraphics_sync(graphics);
693    if (result) return result;
694
695    fb1 = graphics->fb[graphics->cur_fb]; /* the current */
696    fb2 = graphics->fb[NEXT_FB_INDEX(graphics)]; /* the current */
697
698
699    rect = fb2->settings.cliprect;
700    BDBG_MSG(("fb %p, x %d,y %d, width %d, height %d",
701          fb2,
702          rect.x,rect.y,rect.width,rect.height
703          ));
704    /* This will trigger a special case, copying from one buffer to another */
705    if (!graphics->settings.offscreen_framebuffer) {
706        BDBG_ERR((" apply bsurface_copy"));
707        result = bsurface_copy(fb1, &rect, fb2, &rect);
708    }
709    graphics->cur_fb = NEXT_FB_INDEX(graphics);
710    result = bgraphics_p_set_framebuffer(graphics);
711
712    return result;
713}
714
715bresult bgraphics_flip_sync(bgraphics_t graphics)
716{
717    BDBG_OBJECT_ASSERT(graphics, bgraphics);
718
719    return 0;
720}
721
722void bsurface_create_settings_init(bsurface_create_settings *create_settings, bgraphics_t graphics)
723{
724    BDBG_OBJECT_ASSERT(graphics, bgraphics);
725    BKNI_Memset(create_settings, 0, sizeof(*create_settings));
726    create_settings->pixel_format = bgraphics_pixel_format_r5_g6_b5;
727    create_settings->width = 720;
728    create_settings->height = 480;
729    create_settings->alignment = 12; /* 2^12 = 4K alignment needed for RAC. see nexus_dma.h for detailed description of cache coherency requirements. */
730    create_settings->pitch = 0;
731}
732
733/* add a surface according to zorder */
734static void bgraphics_p_add_surface(bgraphics_t g, bsurface_t surface)
735{
736    bsurface_t s;
737    for (s = BLST_Q_FIRST(&g->surfaces);s;s = BLST_Q_NEXT(s, link)) {
738        if (surface->settings.zorder <= s->settings.zorder) {
739            BLST_Q_INSERT_BEFORE(&g->surfaces, s, surface, link);
740            return;
741        }
742    }
743
744    /* just put it at the end */
745    BLST_Q_INSERT_TAIL(&g->surfaces, surface, link);
746}
747
748/* complement of bsurface_p_add_surface */
749static void bgraphics_p_remove_surface(bgraphics_t g, bsurface_t surface)
750{
751    BLST_Q_REMOVE(&g->surfaces, surface, link);
752}
753
754static bsurface_t bsurface_p_create(bgraphics_t graphics, const bsurface_create_settings *create_settings, bool is_fb)
755{
756    bsurface_t surface;
757    NEXUS_SurfaceCreateSettings createSettings;
758    NEXUS_SurfaceMemory mem;
759#if BCHP_CHIP == 7420
760    NEXUS_PlatformConfiguration pConfiguration;
761#endif
762
763    BDBG_OBJECT_ASSERT(graphics, bgraphics);
764    surface = BKNI_Malloc(sizeof(*surface));
765    BKNI_Memset(surface, 0, sizeof(*surface));
766
767    NEXUS_Surface_GetDefaultCreateSettings(&createSettings);
768    createSettings.width = create_settings->width;
769    createSettings.height = create_settings->height;
770    createSettings.alignment = create_settings->alignment;
771    createSettings.pitch = create_settings->pitch;
772    createSettings.pixelFormat = b_graphicspixelformat2nexus(create_settings->pixel_format);
773#if BCHP_CHIP == 7420
774    NEXUS_Platform_GetConfiguration(&pConfiguration);
775    createSettings.heap = pConfiguration.heap[create_settings->heap_index];
776#endif
777
778    surface->nSurface = NEXUS_Surface_Create(&createSettings);
779    if (!surface->nSurface) {
780        BSETTOP_ERROR(berr_external_error);
781        BKNI_Free(surface);
782        return NULL;
783    }
784
785    NEXUS_Surface_GetMemory(surface->nSurface, &mem);
786    surface->mem.buffer = mem.buffer;
787    surface->mem.pitch = mem.pitch;
788    surface->graphics = graphics;
789    surface->is_fb = is_fb;
790    surface->create_settings = *create_settings;
791    surface->settings.position.width = create_settings->width;
792    surface->settings.position.height = create_settings->height;
793    surface->settings.cliprect = surface->settings.position;
794    surface->settings.color = 0xFF000000;
795    surface->settings.alpha = 0xFF; /* matches on in bsettop_base_video */
796
797    if (!is_fb) {
798        /* non-framebuffer surfaces are stored for bgraphics_sync */
799        bgraphics_p_add_surface(graphics, surface);
800    }
801
802    BDBG_OBJECT_SET(surface, bsurface);
803    return surface;
804}
805
806bsurface_t bsurface_create(bgraphics_t graphics, const bsurface_create_settings *create_settings)
807{
808    BDBG_OBJECT_ASSERT(graphics, bgraphics);
809
810    /* Implicitly create a fullscreen framebuffer */
811    if (!graphics->fb[0]) {
812        bvideo_format_settings vs;
813        bsurface_create_settings settings = *create_settings;
814
815        BDBG_WRN(("Implicitly creating framebuffer using first surface settings. "
816            "Call bgraphics_create_framebuffer to be explicit."));
817
818        /* make sure that g_pixel_format_info[] has every enum in the correct order */
819        BDBG_ASSERT(g_pixel_format_info[create_settings->pixel_format].pixel_format == create_settings->pixel_format);
820
821        if (g_pixel_format_info[create_settings->pixel_format].palette) {
822            /* This is because no one's going to want an implicit palette to go
823            along with it. */
824            BDBG_ERR(("Will not implicitly create palettized framebuffer. "
825                "Converting to r5_g6_b5."));
826            settings.pixel_format = bgraphics_pixel_format_r5_g6_b5;
827        }
828
829        bdisplay_get_video_format_settings(&graphics->display->settings, &vs);
830        settings.width = vs.width;
831        settings.height = vs.height;
832        if (!bgraphics_create_framebuffer(graphics, &settings, false))
833            return NULL;
834    }
835
836    return bsurface_p_create(graphics, create_settings, false);
837}
838
839bsurface_t bgraphics_create_framebuffer(bgraphics_t graphics, const bsurface_create_settings *create_settings, unsigned int back_buffer_count)
840{
841    unsigned i;
842
843    BDBG_OBJECT_ASSERT(graphics, bgraphics);
844    if (graphics->fb[0]) {
845        BDBG_WRN(("already created"));
846        return graphics->fb[0];
847    }
848
849    if (back_buffer_count >= MAX_GRAPHICS_FBS) {
850        BSETTOP_ERROR(berr_invalid_parameter);
851        back_buffer_count = 2;
852    }
853
854    graphics->fb[0] = bsurface_p_create(graphics, create_settings, true);
855    if (back_buffer_count > 0) {
856        graphics->fb[1] = bsurface_p_create(graphics, create_settings, true);
857        if (back_buffer_count > 1) {
858            graphics->fb[2] = bsurface_p_create(graphics, create_settings, true);
859        }
860    }
861    graphics->cur_fb = 0;
862    graphics->num_fbs = back_buffer_count + 1;
863
864    for (i=0;i<graphics->num_fbs;i++) {
865        if (graphics->fb[i]) {
866            BKNI_Memset(graphics->fb[i]->mem.buffer, 0, graphics->fb[i]->mem.pitch * create_settings->height);
867        }
868    }
869
870    bgraphics_p_set_framebuffer(graphics);
871
872    return graphics->fb[0];
873}
874
875bsurface_t bsurface_get_display(bgraphics_t graphics, const bsurface_create_settings *create_settings)
876{
877    /* create a single buffered framebuffer */
878    return bgraphics_create_framebuffer(graphics, create_settings, 0);
879}
880
881void bsurface_destroy(bsurface_t surface)
882{
883    BDBG_OBJECT_ASSERT(surface, bsurface);
884
885    if (surface->is_fb && !surface->graphics->closing) {
886        BDBG_ERR(("cannot destroy framebuffer"));
887        return;
888    }
889
890    BLST_Q_REMOVE(&surface->graphics->surfaces, surface, link);
891
892    if (surface->nSurface) {
893        NEXUS_Surface_Destroy(surface->nSurface);
894    }
895    BDBG_OBJECT_UNSET(surface, bsurface);
896    BKNI_Free(surface);
897}
898
899bresult bsurface_get_memory(bsurface_t surface, bsurface_memory *memory)
900{
901    if (surface->is_fb) {
902        surface = surface->graphics->fb[NEXT_FB_INDEX(surface->graphics)];
903    }
904    *memory = surface->mem;
905    return 0;
906}
907
908bresult bsurface_set(bsurface_t surface, const bsurface_settings *settings)
909{
910    /* store fb settings in all fbs */
911    if (surface->is_fb) {
912        unsigned i;
913        for (i=0;i<surface->graphics->num_fbs;i++) {
914            surface->graphics->fb[i]->settings = *settings;
915        }
916        /* reset the frame buffer to reapply settings */
917        bgraphics_p_set_framebuffer(surface->graphics);
918    }
919    else {
920        bool reorder = surface->settings.zorder != settings->zorder;
921        surface->settings = *settings;
922        /* remove and readd in order to pick up zorder changes */
923        if (reorder) {
924            bgraphics_p_remove_surface(surface->graphics, surface);
925            bgraphics_p_add_surface(surface->graphics, surface);
926        }
927    }
928    return 0;
929}
930
931void bsurface_get(bsurface_t surface, bsurface_settings *settings)
932{
933    BDBG_OBJECT_ASSERT(surface, bsurface);
934    *settings = surface->settings;
935}
936
937#if !B_N_GRC
938static bresult bsurface_p_cpu_scalecopy(
939    bsurface_t destsurface, const bsettop_rect *destrect,
940    bsurface_t srcsurface, const bsettop_rect *srcrect)
941{
942#if B_HAS_SOFT_GFX
943    B_SoftGfx_BlitSettings sBlitSettings;
944    B_SoftGfxHandle handle = NULL;
945
946    handle = B_SoftGfx_Open(NULL);
947
948    B_SoftGfx_GetDefaultBlitSettings(&sBlitSettings);
949
950    sBlitSettings.srcsurface = srcsurface->nSurface;
951    sBlitSettings.outsurface = destsurface->nSurface;
952
953    sBlitSettings.srcrect.x     = (int16_t)srcrect->x;
954    sBlitSettings.srcrect.y     = (int16_t)srcrect->y;
955    sBlitSettings.srcrect.width = (uint16_t)srcrect->width;
956    sBlitSettings.srcrect.height= (uint16_t)srcrect->height;
957
958    sBlitSettings.outx = (int16_t)destrect->x;
959    sBlitSettings.outy = (int16_t)destrect->y;
960
961    sBlitSettings.colorOp = B_SoftGfx_BlitColorOp_eCopySource;
962    sBlitSettings.alphaOp = B_SoftGfx_BlitAlphaOp_eCopySource;
963
964#if BCHP_CHIP == 7550
965    /* Color conversion for surfaces going to GFD1.*/
966    if ((destsurface->create_settings.pixel_format == bgraphics_pixel_format_a8_y8_cb8_cr8)
967        &&( destsurface->graphics->display->index == 1))
968    {
969        int i;
970        sBlitSettings.conversionMatrixEnabled = true;
971
972        for(i=0; i<20; i++)
973        {
974            sBlitSettings.conversionMatrix.coeffMatrix[i] =
975            (destsurface->graphics->display->settings.format == NEXUS_VideoFormat_ePalD) ?
976                g_ai32_Matrix_RGBtoYCbCr_BT_601[i]: g_ai32_Matrix_RGBtoYCbCr_BT_709[i];
977        }
978        sBlitSettings.conversionMatrix.shift = 8;
979    }
980
981#endif
982
983    B_SoftGfx_Blit(handle, &sBlitSettings);
984
985    B_SoftGfx_Close(handle);
986    return b_ok;
987#else
988
989    int h,w,y,bpp,w_bytes,srch;
990    unsigned char *pSrc, *pDst;
991
992    if ( destsurface->create_settings.pixel_format !=
993         srcsurface->create_settings.pixel_format )
994    {
995        BDBG_WRN(("Unable to software copy when pixel formats don't match!"));
996        return b_ok;
997    }
998
999    /* Set starting memory addresses based upon rectangles */
1000    pSrc = (unsigned char *)srcsurface->mem.buffer;
1001    pDst = (unsigned char *)destsurface->mem.buffer;
1002    pSrc += srcsurface->mem.pitch*srcrect->y;
1003    pDst += destsurface->mem.pitch*destrect->y;
1004
1005    /* No horizontal scaling, use the smaller of the two widths */
1006    if ( srcrect->width > destrect->width )
1007        w = destrect->width;
1008    else
1009        w = srcrect->width;
1010
1011    /* No vertical downscaling, use smaller of the two heights */
1012    if ( srcrect->height > destrect->height )
1013        srch = destrect->height;
1014    else
1015        srch = srcrect->height;
1016    h = destrect->height;
1017
1018    /* Need to calculate #bytes to copy per scanline */
1019    bpp = g_pixel_format_info[srcsurface->create_settings.pixel_format].bpp;
1020    w_bytes = (w*bpp)/8;    /* Not doing partial byte copies for indexed formats */
1021
1022    /* Add in horizontal offsets */
1023    pDst += (destrect->x*bpp)/8;
1024    pSrc += (srcrect->x*bpp)/8;
1025
1026    /* Simple line-doubling for now... */
1027    for ( y = 0; y < h; y++ )
1028    {
1029        BKNI_Memcpy(pDst, pSrc, w_bytes);
1030        pDst += destsurface->mem.pitch;
1031
1032        if ( ((y * srch)/h) !=
1033             (((y+1) * srch)/h) )
1034        {
1035            pSrc += srcsurface->mem.pitch;
1036        }
1037    }
1038
1039    if (!destsurface->settings.disable_automatic_cache_flush) {
1040        NEXUS_Surface_Flush(destsurface->nSurface);
1041    }
1042
1043    return b_ok;
1044#endif /* B_HAS_SOFT_GFX */
1045}
1046
1047#if !B_HAS_SOFT_GFX
1048static bgraphics_pixel bgraphics_p_make_pixel(bgraphics_pixel_format pixel_format,
1049    uint32_t a, uint32_t r, uint32_t g, uint32_t b)
1050{
1051    switch (pixel_format) {
1052    case bgraphics_pixel_format_r5_g6_b5:
1053        return (r&0xf8)<<8 | (g&0xfc)<<3 | (b&0xf8)>>3;
1054    case bgraphics_pixel_format_a1_r5_g5_b5:
1055        return (a?1:0)<<15 | (r&0xf8)<<7 | (g&0xf8)<<2 | (b&0xf8)>>3;
1056    case bgraphics_pixel_format_r5_g5_b5_a1:
1057        return (r&0xf8)<<8 | (g&0xf8)<<3 | (b&0xf8)>>2 | (a?1:0)<<0;
1058    case bgraphics_pixel_format_a4_r4_g4_b4:
1059        return (a&0xf0)<<8 | (r&0xf0)<<4 | (g&0xf0)<<0 | (b&0xf0)>>4;
1060    case bgraphics_pixel_format_r4_g4_b4_a4:
1061        return (r&0xf0)<<8 | (g&0xf0)<<4 | (b&0xf0)<<0 | (a&0xf0)>>4;
1062
1063    case bgraphics_pixel_format_a8_r8_g8_b8:
1064        return (a)<<24 | (r)<<16 | (g)<<8 | (b)<<0;
1065
1066    case bgraphics_pixel_format_y08_cb8_y18_cr8:
1067    case bgraphics_pixel_format_cr8_y18_cb8_y08:
1068        BDBG_WRN(("not supported yet"));
1069        return 0;
1070
1071    case bgraphics_pixel_format_palette8:
1072    case bgraphics_pixel_format_a8_palette8:
1073    case bgraphics_pixel_format_palette2:
1074    case bgraphics_pixel_format_palette4:
1075    case bgraphics_pixel_format_a0:
1076    case bgraphics_pixel_format_a8:
1077    case bgraphics_pixel_format_video_tunnel:
1078        break;
1079    }
1080    return 0; /* no conversion */
1081}
1082#endif
1083
1084static bresult bsurface_p_cpu_fill(bsurface_t surface, const bsettop_rect *rect, bgraphics_pixel pixel)
1085{
1086#if B_HAS_SOFT_GFX
1087    B_SoftGfx_FillSettings sFillSettings;
1088    B_SoftGfxHandle handle = NULL;
1089
1090    handle = B_SoftGfx_Open(NULL);
1091
1092    B_SoftGfx_GetDefaultFillSettings(&sFillSettings);
1093
1094    sFillSettings.surface = surface->nSurface;
1095    sFillSettings.color = (NEXUS_Pixel) pixel;
1096    sFillSettings.rect.x     = (int16_t)rect->x;
1097    sFillSettings.rect.y     = (int16_t)rect->y;
1098    sFillSettings.rect.width = (uint16_t)rect->width;
1099    sFillSettings.rect.height= (uint16_t)rect->height;
1100    sFillSettings.colorOp = B_SoftGfx_FillOp_eCopy;
1101    sFillSettings.alphaOp = B_SoftGfx_FillOp_eCopy;
1102
1103    B_SoftGfx_Fill(handle, &sFillSettings);
1104
1105    B_SoftGfx_Close(handle);
1106    return b_ok;
1107#else
1108
1109    int h,w,y,bpp,w_bytes;
1110    unsigned char *pDst;
1111    unsigned long mask=0;
1112
1113    /* Set starting memory addresses based upon rectangles */
1114    pDst = (unsigned char *)surface->mem.buffer;
1115    pDst += surface->mem.pitch*rect->y;
1116    h=rect->height;
1117    w=rect->width;
1118
1119    switch (surface->create_settings.pixel_format) {
1120    case bgraphics_pixel_format_palette2:
1121        pixel = (pixel & 0x3) << 6;
1122        pixel |= (pixel>>4) | (pixel>>2) | (pixel>>6);
1123        mask=0xff;
1124        break;
1125    case bgraphics_pixel_format_palette4:
1126        pixel = (pixel & 0xF) << 4;
1127        pixel |= (pixel>>4);
1128        mask=0xff;
1129        break;
1130    case bgraphics_pixel_format_a8_palette8:
1131        pixel = ((pixel & 0xFF00) << 16) | (pixel & 0xFF);
1132        mask=0xff;
1133        break;
1134    case bgraphics_pixel_format_a8:
1135        pixel = (pixel & 0xFF) << 24;
1136        mask=0xff000000;
1137        break;
1138#if 0
1139/* TODO */
1140    case bgraphics_pixel_format_y08_cb8_y18_cr8:
1141        {
1142        unsigned int aycrcb_pixel;
1143        NEXUS_ConvertPixel_RGBtoYCbCr(BPXL_eA8_Y8_Cb8_Cr8, BPXL_eA8_R8_G8_B8, pixel, &aycrcb_pixel);
1144        BDBG_MSG(("convert pixel on fill %08x => %08x", pixel, aycrcb_pixel));
1145        pixel = aycrcb_pixel;
1146        mask=0xffffffff;
1147        }
1148        break;
1149#endif
1150    case bgraphics_pixel_format_r5_g6_b5:         /* 16-bit, no per-pixel alpha */
1151    case bgraphics_pixel_format_a1_r5_g5_b5:      /* 16-bit */
1152    case bgraphics_pixel_format_r5_g5_b5_a1:      /* 16-bit */
1153    case bgraphics_pixel_format_a4_r4_g4_b4:      /* 16-bit */
1154    case bgraphics_pixel_format_r4_g4_b4_a4:      /* 16-bit */
1155        mask=0xffff;
1156        break;
1157    case bgraphics_pixel_format_a8_r8_g8_b8:      /* 32-bit */
1158        mask=0xffffffff;
1159        break;
1160    default:
1161        BDBG_ERR(("Unsupported software fill pixel format"));
1162        return b_ok;
1163    }
1164
1165    bpp = g_pixel_format_info[surface->create_settings.pixel_format].bpp;
1166    w_bytes = (w*bpp)/8;    /* Not doing partial byte copies for indexed formats */
1167
1168    /* Add in horizontal offset */
1169    pDst += (rect->x*bpp)/8;
1170
1171    if ( mask == 0xff )
1172    {
1173        /* 8-bit memset */
1174        for ( y = 0; y < h; y++ )
1175        {
1176            BKNI_Memset(pDst, pixel, w_bytes);
1177            pDst += surface->mem.pitch;
1178        }
1179    }
1180    else if ( mask == 0xffff )
1181    {
1182        /* 16-bit copy */
1183        int x;
1184        pixel = bgraphics_p_make_pixel(surface->create_settings.pixel_format,
1185                                pixel>>24,
1186                                (pixel>>16)&0xff,
1187                                (pixel>>8)&0xff,
1188                                pixel&0xff);
1189        for ( y = 0; y < h; y++ )
1190        {
1191            unsigned short *pDst16=(unsigned short *)pDst;
1192            for (x = 0; x < w; x++ )
1193            {
1194                pDst16[x] = (unsigned short)pixel;
1195            }
1196            pDst += surface->mem.pitch;
1197        }
1198    }
1199    else
1200    {
1201        /* 32-bit copy w/mask */
1202        int x;
1203        for ( y = 0; y < h; y++ )
1204        {
1205            unsigned long *pDst32=(unsigned long *)pDst;
1206            for (x = 0; x < w; x++ )
1207            {
1208                pDst32[x] = (unsigned long)pixel | (pDst32[x] & ~mask);
1209            }
1210            pDst += surface->mem.pitch;
1211        }
1212    }
1213    return b_ok;
1214#endif /* B_HAS_SOFT_GFX */
1215}
1216#endif
1217
1218
1219bresult bsurface_fill(bsurface_t surface, const bsettop_rect *rect, bgraphics_pixel pixel)
1220{
1221    BDBG_OBJECT_ASSERT(surface, bsurface);
1222    return bsurface_blended_fill( surface, rect, pixel, BSURFACE_FILL_COPY_COLOR );
1223}
1224
1225bresult bsurface_copy(bsurface_t destsurface, const bsettop_rect *destrect, bsurface_t srcsurface, const bsettop_rect *srcrect)
1226{
1227    BDBG_MSG(("bsurface_copy from %p (%d,%d,%dx%d) to %p (%d,%d,%dx%d)",
1228        srcsurface, srcrect?srcrect->x:0, srcrect?srcrect->y:0, srcrect?srcrect->width:0, srcrect?srcrect->height:0,
1229        destsurface, destrect?destrect->x:0, destrect?destrect->y:0, destrect?destrect->width:0, destrect?destrect->height:0));
1230
1231#if B_N_GRC
1232    /* This copies the source and sets the destinations alpha channel to opaque. */
1233    return bsurface_blit(destsurface, destrect,
1234        BSURFACE_BLEND_WITH_PIXEL1|BSURFACE_SET_DEST_ALPHA_WITH_SRC1_ALPHA,
1235        srcsurface, srcrect, NULL, NULL, 0xFF, 0xFF);
1236#else
1237    if (destsurface->is_fb) {
1238        destsurface = destsurface->graphics->fb[NEXT_FB_INDEX(destsurface->graphics)];
1239    }
1240    if (srcsurface->is_fb) {
1241        srcsurface = destsurface->graphics->fb[NEXT_FB_INDEX(srcsurface->graphics)];
1242    }
1243    bsurface_p_cpu_scalecopy(destsurface, destrect, srcsurface, srcrect);
1244    if (!destsurface->settings.disable_automatic_cache_flush) {
1245        NEXUS_Surface_Flush(destsurface->nSurface);
1246    }
1247    return 0;
1248#endif
1249}
1250
1251bresult bsurface_blit(bsurface_t destsurface, const bsettop_rect *destrect, uint32_t operation,
1252 bsurface_t src1, const bsettop_rect *src1_rect, bsurface_t src2, const bsettop_rect *src2_rect, bgraphics_pixel pixel1,
1253 bgraphics_pixel pixel2)
1254{
1255#if B_N_GRC
1256    bsurface_blit_params params;
1257
1258    if (!destsurface) {
1259        return BSETTOP_ERROR(berr_invalid_parameter);
1260    }
1261
1262#if 0
1263/* TODO: in order to use FastBlit, we have to screen out a variety of issues including YCrCb/RGB conversion. */
1264    if (src2) {
1265#endif
1266        bsurface_blit_params_init(&params);
1267        params.operation = operation;
1268        params.src1 = src1;
1269        if (src1_rect) {
1270            params.src1_rect = *src1_rect;
1271        }
1272        params.src2 = src2;
1273        if ( src2_rect )
1274        {
1275            params.src2_rect = *src2_rect;
1276        }
1277        params.pixel1 = pixel1;
1278        params.pixel2 = pixel2;
1279        return bsurface_extended_blit(destsurface, destrect, &params);
1280#if 0
1281    }
1282    else {
1283        NEXUS_Rect outputRect, sourceRect;
1284        NEXUS_Error rc;
1285
1286        COPY_RECT(&sourceRect, src1_rect);
1287        COPY_RECT(&outputRect, destrect);
1288
1289        NEXUS_Surface_Flush(destsurface->nSurface);
1290        NEXUS_Surface_Flush(src1->nSurface);
1291
1292        rc = NEXUS_Graphics2D_FastBlit(destsurface->graphics->graphics2d,
1293            destsurface->nSurface,
1294            &outputRect,
1295            src1->nSurface,
1296            &sourceRect,
1297            NEXUS_BlitColorOp_eCopySource, /* TODO */
1298            NEXUS_BlitAlphaOp_eCopySource, /* TODO */
1299            pixel1);
1300        if (rc) return BSETTOP_ERROR(rc);
1301
1302        if (!destsurface->graphics->settings.async_blits) {
1303            bgraphics_p_checkpoint(destsurface->graphics);
1304        }
1305
1306        return 0;
1307    }
1308#endif
1309#else
1310    BSTD_UNUSED(destsurface);
1311    BSTD_UNUSED(destrect);
1312    BSTD_UNUSED(operation);
1313    BSTD_UNUSED(src1);
1314    BSTD_UNUSED(src2);
1315    BSTD_UNUSED(src1_rect);
1316    BSTD_UNUSED(src2_rect);
1317    BSTD_UNUSED(pixel1);
1318    BSTD_UNUSED(pixel2);
1319    BDBG_WRN(("Dropping software blit request"));
1320    return 0;
1321#endif
1322}
1323
1324
1325void bsurface_blit_params_init(bsurface_blit_params *params)
1326{
1327    BKNI_Memset(params, 0, sizeof(*params));
1328}
1329
1330bresult bsurface_extended_blit(bsurface_t destsurface, const bsettop_rect *destrect, const bsurface_blit_params *params)
1331{
1332#if B_N_GRC
1333    NEXUS_Graphics2DBlitSettings blitSettings;
1334    NEXUS_Error rc;
1335    bsurface_t src1 = params->src1;
1336
1337    if (!src1 || !destsurface) {
1338        return BSETTOP_ERROR(berr_invalid_parameter);
1339    }
1340    if (destsurface->is_fb &&
1341        src1->is_fb &&
1342        !params->src2 &&
1343        src1->graphics == destsurface->graphics &&
1344        params->operation == (BSURFACE_BLEND_WITH_PIXEL1|BSURFACE_SET_DEST_ALPHA_WITH_SRC1_ALPHA))
1345    {
1346        /* detect a special case for handling double buffering */
1347        BDBG_ERR(("double buffer"));
1348    } else {
1349        if (destsurface->is_fb) {
1350            destsurface = destsurface->graphics->fb[NEXT_FB_INDEX(destsurface->graphics)];
1351        }
1352        if (src1->is_fb) {
1353            src1 = src1->graphics->fb[NEXT_FB_INDEX(src1->graphics)];
1354        }
1355    }
1356
1357    NEXUS_Graphics2D_GetDefaultBlitSettings(&blitSettings);
1358
1359    blitSettings.source.surface = src1->nSurface;
1360    if ( 0 == params->src1_rect.width && 0 == params->src1_rect.height ) {
1361        blitSettings.dest.rect.width = params->src1->create_settings.width;
1362        blitSettings.dest.rect.height = params->src1->create_settings.height;
1363    }
1364    else {
1365        COPY_RECT(&blitSettings.source.rect, &params->src1_rect);
1366    }
1367    if (params->src2) {
1368        blitSettings.dest.surface = params->src2->nSurface;
1369        if ( 0 == params->src2_rect.width && 0 == params->src2_rect.height ) {
1370            blitSettings.dest.rect.width = params->src2->create_settings.width;
1371            blitSettings.dest.rect.height = params->src2->create_settings.height;
1372        }
1373        else {
1374            COPY_RECT(&blitSettings.dest.rect, &params->src2_rect);
1375        }
1376    }
1377    blitSettings.output.surface = destsurface->nSurface;
1378    COPY_RECT(&blitSettings.output.rect, destrect);
1379
1380    /* TODO: support every params->operation */
1381    if (params->operation & BSURFACE_BLEND_WITH_SRC1_ALPHA) {
1382        blitSettings.colorOp = NEXUS_BlitColorOp_eUseSourceAlpha;
1383    }
1384    else if (params->operation & BSURFACE_BLEND_WITH_SRC2_ALPHA) {
1385        blitSettings.colorOp = NEXUS_BlitColorOp_eUseDestAlpha;
1386    }
1387    else if (params->pixel1 != 0xFF) {
1388        blitSettings.colorOp = NEXUS_BlitColorOp_eUseConstantAlpha;
1389        blitSettings.constantColor = params->pixel1;
1390    }
1391    else {
1392        blitSettings.colorOp = NEXUS_BlitColorOp_eCopySource;
1393    }
1394
1395    if (params->operation & BSURFACE_SET_DEST_ALPHA_WITH_SRC1_ALPHA) {
1396        blitSettings.alphaOp = NEXUS_BlitAlphaOp_eCopySource;
1397    }
1398    else if (params->operation & BSURFACE_SET_DEST_ALPHA_WITH_SRC2_ALPHA) {
1399        blitSettings.alphaOp = NEXUS_BlitAlphaOp_eCopyDest;
1400    }
1401    else if (params->operation & BSURFACE_SET_DEST_ALPHA_WITH_AVG_ALPHA) {
1402        blitSettings.alphaOp = NEXUS_BlitAlphaOp_eCombine;
1403    }
1404    else {
1405        blitSettings.alphaOp = NEXUS_BlitAlphaOp_eCopyConstant;
1406        blitSettings.constantColor |= params->pixel1 & 0xFF000000;
1407    }
1408
1409    NEXUS_Surface_Flush(destsurface->nSurface);
1410    NEXUS_Surface_Flush(src1->nSurface);
1411    if (params->src2) {
1412        NEXUS_Surface_Flush(params->src2->nSurface);
1413    }
1414
1415    rc = NEXUS_Graphics2D_Blit(destsurface->graphics->graphics2d, &blitSettings);
1416    if (rc) {
1417        BKNI_Fail();
1418        return BSETTOP_ERROR(berr_external_error);
1419    }
1420
1421    if (!destsurface->graphics->settings.async_blits) {
1422        bgraphics_p_checkpoint(destsurface->graphics);
1423    }
1424#else
1425    bsurface_t src1 = params->src1;
1426
1427    if (!src1 || !destsurface) {
1428        return BSETTOP_ERROR(berr_invalid_parameter);
1429    }
1430
1431    if (destsurface->is_fb) {
1432        destsurface = destsurface->graphics->fb[NEXT_FB_INDEX(destsurface->graphics)];
1433    }
1434    if (src1 && src1->is_fb) {
1435        src1 = src1->graphics->fb[NEXT_FB_INDEX(src1->graphics)];
1436    }
1437
1438    BSTD_UNUSED(destrect);
1439
1440    BDBG_WRN(("Dropping software blit request"));
1441#endif
1442
1443    return b_ok;
1444}
1445
1446bresult
1447bsurface_blended_fill(bsurface_t surface, const bsettop_rect *rect, bgraphics_pixel pixel, uint32_t operation)
1448{
1449#if B_N_GRC
1450    NEXUS_Graphics2DFillSettings fillSettings;
1451    NEXUS_Error rc;
1452
1453    BDBG_OBJECT_ASSERT(surface, bsurface);
1454    if (surface->is_fb) {
1455        surface = surface->graphics->fb[NEXT_FB_INDEX(surface->graphics)];
1456    }
1457
1458    BDBG_MSG(("bsurface_blended_fill %p %d,%d,%dx%d with %#x",
1459        surface, rect?rect->x:0, rect?rect->y:0, rect?rect->width:0, rect?rect->height:0,
1460        pixel));
1461    BSTD_UNUSED(operation);
1462
1463    NEXUS_Graphics2D_GetDefaultFillSettings(&fillSettings);
1464
1465    fillSettings.surface = surface->nSurface;
1466    COPY_RECT(&fillSettings.rect, rect);
1467
1468    /* TODO */
1469    fillSettings.colorOp = NEXUS_FillOp_eCopy;
1470    fillSettings.alphaOp = NEXUS_FillOp_eCopy;
1471    fillSettings.color = pixel;
1472
1473    NEXUS_Surface_Flush(surface->nSurface);
1474    rc = NEXUS_Graphics2D_Fill(surface->graphics->graphics2d, &fillSettings);
1475    if (rc) return BSETTOP_ERROR(berr_external_error);
1476
1477    if (!surface->graphics->settings.async_blits) {
1478        bgraphics_p_checkpoint(surface->graphics);
1479    }
1480    return 0;
1481#else
1482    BDBG_OBJECT_ASSERT(surface, bsurface);
1483    if (surface->is_fb) {
1484        surface = surface->graphics->fb[NEXT_FB_INDEX(surface->graphics)];
1485    }
1486
1487    BDBG_MSG(("bsurface_blended_fill %p %d,%d,%dx%d with %#x",
1488        surface, rect?rect->x:0, rect?rect->y:0, rect?rect->width:0, rect?rect->height:0,
1489        pixel));
1490    if( (operation&0xF) == BSURFACE_FILL_COPY_COLOR ) {
1491        bsurface_p_cpu_fill(surface, rect, pixel);
1492        if (!surface->settings.disable_automatic_cache_flush) {
1493            NEXUS_Surface_Flush(surface->nSurface);
1494        }
1495        return b_ok;
1496    }
1497    else
1498        return BSETTOP_ERROR(berr_external_error);
1499#endif
1500}
1501
1502bresult bsurface_load_clut(bsurface_t s, bgraphics_palette palette)
1503{
1504    NEXUS_SurfaceMemory mem;
1505    unsigned n;
1506
1507    NEXUS_Surface_GetMemory(s->nSurface, &mem);
1508    n = palette.length;
1509    if (n > mem.numPaletteEntries) {
1510        n = mem.numPaletteEntries;
1511    }
1512
1513    BDBG_ASSERT(sizeof(bgraphics_pixel) == sizeof(NEXUS_Pixel));
1514    BKNI_Memcpy(mem.palette, palette.palette, n * sizeof(bgraphics_pixel));
1515
1516    NEXUS_Surface_Flush(s->nSurface);
1517
1518    return 0;
1519}
1520
1521NEXUS_SurfaceHandle bsurface_get_nexus_handle(bsurface_t surface)
1522{
1523        BDBG_OBJECT_ASSERT(surface, bsurface);
1524        return surface->nSurface;
1525}
1526
Note: See TracBrowser for help on using the repository browser.