source: svn/trunk/newcon3bcm2_21bu/nexus/modules/graphics2d/7552/src/nexus_graphics2d.c

Last change on this file was 2, checked in by phkim, 11 years ago

1.phkim

  1. revision copy newcon3sk r27
  • Property svn:executable set to *
File size: 62.1 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_graphics2d.c $
39 * $brcm_Revision: 122 $
40 * $brcm_Date: 12/19/11 10:06a $
41 *
42 * Module Description:
43 *
44 * Revision History:
45 *
46 * $brcm_Log: /nexus/modules/graphics2d/7400/src/nexus_graphics2d.c $
47 *
48 * 122   12/19/11 10:06a erickson
49 * SW7425-1795: allow NULL packet buffer heap. validate driver-side CPU
50 *  accessibility at GetPacketBuffer.
51 *
52 * 121   12/16/11 4:47p erickson
53 * SW7425-1795: back out packet_buffer_heap until it can be validated for
54 *  driver user
55 *
56 * 120   12/8/11 10:58a erickson
57 * SW7425-1921: it is valid if colorKey.dest.enabled is set with no dest
58 *  surface. in that case, take dest constant color.
59 *
60 * 119   12/8/11 9:48a erickson
61 * SW7420-2155: auto-mirror if the output overlaps the source
62 *
63 * 118   11/29/11 11:39a erickson
64 * SW7420-2129: get current default heap using NEXUS_P_DefaultHeap
65 *
66 * 117   11/28/11 2:24p erickson
67 * SW7425-1795: set packet_buffer_heap
68 *
69 * 116   10/31/11 9:20a erickson
70 * SW7358-175: fix palette YCrCb test
71 *
72 * 115   10/27/11 1:19p erickson
73 * SW7231-415: non-polling Checkpoint must fail if previously issued
74 *  checkpoint has not completed
75 *
76 * 114   10/26/11 12:02p jtna
77 * SW7231-406: disable grc callback before standby. re-enable after resume
78 *
79 * 113   10/25/11 5:10p jtna
80 * SW7231-406: simplify graphics2d power management
81 *
82 * 112   9/7/11 12:47p erickson
83 * SW7420-1009: support NEXUS_ANY_ID
84 *
85 * 111   8/24/11 10:09a erickson
86 * SW7420-1894: add checkpoint watchdog if packetFifoThreshold is non-
87 *  zero. helps debug apps that aren't calling checkpoint.
88 *
89 * 110   8/9/11 2:35p mward
90 * SW7125-1072: add coverity hint for BLST usage
91 *
92 * 109   7/21/11 5:29p erickson
93 * SW7420-1974: add option for separate dest and source constant color
94 *
95 * 108   7/21/11 4:13p gmohile
96 * SW7125-1014 : Rework power management
97 *
98 * SW7125-1014/1   7/20/11 4:37p gmohile
99 * SW7125-1014 : Rework power management
100 *
101 * 107   7/1/11 4:05p erickson
102 * SW7420-1974: fix dest colorkey test
103 *
104 * 106   6/2/11 1:55p gmohile
105 * SW7231-128 : Add SRAM power down
106 *
107 * 105   5/31/11 1:17p erickson
108 * SW7420-1200: fix warnings
109 *
110 * 104   5/26/11 1:13p erickson
111 * SW7420-1894: deprecate preAllocPacketMemory and maxOperations from
112 *  NEXUS_Graphics2DOpenSettings
113 *
114 * 103   5/24/11 4:03p erickson
115 * SW7346-149: support multiplexing of packet and function-based blit by
116 *  using two GRC packet contexts within a single NEXUS_Graphics2D context
117 *
118 * 102   5/24/11 3:14p erickson
119 * SW7420-1200: reduce cpu util on blit
120 *
121 * 101   5/23/11 4:50p erickson
122 * SW7420-1200: refactor grclib for optimal nexus use
123 *
124 * 100   5/20/11 5:03p erickson
125 * SW7420-1894: add NEXUS_Graphics2DOpenSettings.packetFifoThreshold
126 *
127 * 99   4/14/11 3:37p jtna
128 * SWDTV-6321: fix build warnings for 2.6.37 kernel
129 *
130 * 98   3/25/11 12:41p erickson
131 * SW7420-1671: Graphics2DModule must clean up on uninit to help with
132 *  error recovery
133 *
134 * 97   2/25/11 2:52p gmohile
135 * SW7408-210 : Deprecate use of NEXUS_POWER_STANDBY
136 *
137 * 96   2/15/11 5:33p gmohile
138 * SW7408-210 : Merge initial version of module standby
139 *
140 * 95   2/14/11 9:22p spothana
141 * SW7420-1493: Get packet buffer sometimes submits blit commands when the
142 *  power to graphics engine is off.
143 *
144 * 94   1/20/11 6:12p erickson
145 * SW7405-5063: add NEXUS_FillOp_eUseBlendEquation
146 *
147 * 93   12/28/10 1:42p erickson
148 * SW7420-1138: standardize on NEXUS_NUM_2D_ENGINES
149 *
150 * 92   12/7/10 5:44p erickson
151 * SW7420-1138: add boundsHeap
152 *
153 * 91   12/3/10 6:54p mphillip
154 * SW7325-826: Initialize blit params for palette blitting
155 *
156 * 90   11/16/10 3:29p erickson
157 * SW7420-1200: add BERR_OUT_OF_DEVICE_MEMORY check as normal
158 *
159 * 89   11/2/10 8:08p spothana
160 * SW7420-1222: Power on graphics before checking status and submitting
161 *  packets.
162 *
163 * 88   10/28/10 5:47p jtna
164 * SW7405-4810: add checkpoint-based gfx2d power management
165 *
166 * 87   10/15/10 9:19a erickson
167 * SW7405-4943: NEXUS_Graphics2D_Blit should validate dest surface if
168 *  colorkey is requested
169 *
170 * 86   9/22/10 5:11p erickson
171 * SW7405-4882: add NEXUS_Graphics2D_ConvertFilter and
172 *  NEXUS_Graphics2D_ConvertColorMatrix
173 *
174 * 85   8/20/10 11:33a erickson
175 * SW7405-3671: clean up indenting, BDBG_MSG, priv function name
176 *
177 * 84   8/18/10 4:53p erickson
178 * SW7405-3671: add simple dynamic power management support
179 *
180 * 83   8/16/10 11:08a erickson
181 * SW7405-3671: add packet blit API. switch to packet-based GRC
182 *  implementation.
183 *
184 **************************************************************************/
185#include "nexus_graphics2d_module.h"
186#include "nexus_graphics2d_impl.h"
187#include "nexus_power_management.h"
188
189BDBG_MODULE(nexus_graphics2d);
190BTRC_MODULE(nexus_graphics2d_blit, ENABLE);
191
192NEXUS_ModuleHandle g_NEXUS_graphics2DModule;
193struct Graphics2DData g_NEXUS_graphics2DData;
194
195#define BDBG_PRINT_OP(x)    /* BDBG_MSG(x) */
196
197/* NEXUS_NUM_2D_ENGINES is typically set in nexus_platform_features.h */
198#ifndef NEXUS_NUM_2D_ENGINES
199#if BCHP_CHIP==7438 || BCHP_CHIP==7440
200#define NEXUS_NUM_2D_ENGINES 2
201#else
202#define NEXUS_NUM_2D_ENGINES 1
203#endif
204#endif
205
206static struct NEXUS_Graphics2DEngine g_grcInstance[NEXUS_NUM_2D_ENGINES];
207
208static BERR_Code NEXUS_Graphics2D_PacketCallback_isr( BGRC_Handle grc, void *data );
209static void NEXUS_Graphics2D_P_PacketAdvance( void *context );
210static void nexus_graphics2d_p_checkpoint_watchdog(void *context);
211
212/****************************************
213* Module functions
214***************/
215
216void NEXUS_Graphics2DModule_GetDefaultSettings(NEXUS_Graphics2DModuleSettings *pSettings)
217{
218    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
219}
220
221NEXUS_ModuleHandle NEXUS_Graphics2DModule_Init(const NEXUS_Graphics2DModuleSettings *pSettings)
222{
223    NEXUS_ModuleSettings moduleSettings;
224    BDBG_ASSERT(!g_NEXUS_graphics2DModule);
225
226    if (!pSettings) {
227        BDBG_ERR(("Graphics2D requires Surface handle. Cannot Init with NULL."));
228        return NULL;
229    }
230
231    /* init global module handle */
232    NEXUS_Module_GetDefaultSettings(&moduleSettings);
233    moduleSettings.priority = NEXUS_ModulePriority_eLow;
234    g_NEXUS_graphics2DModule = NEXUS_Module_Create("graphics2d", &moduleSettings);
235    if (!g_NEXUS_graphics2DModule) {
236        return NULL;
237    }
238
239    BKNI_Memset(g_grcInstance, 0, sizeof(g_grcInstance));
240    g_NEXUS_graphics2DData.settings = *pSettings;
241   
242    NEXUS_PowerManagement_SetCoreState(NEXUS_PowerManagementCore_eGraphics2DMemory, true);
243   
244    return g_NEXUS_graphics2DModule;
245}
246
247void NEXUS_Graphics2DModule_Uninit()
248{
249    unsigned i;
250   
251    /* check if handles left open */
252    for (i=0;i<NEXUS_NUM_2D_ENGINES;i++) {
253        struct NEXUS_Graphics2DEngine *engine = &g_grcInstance[i];
254        NEXUS_Graphics2DHandle gfx;
255        /* coverity[use_after_free] */
256        while ((gfx = BLST_S_FIRST(&engine->contexts))) {
257            BDBG_WRN(("auto-close NEXUS_Graphics2D %p", gfx));
258            NEXUS_Graphics2D_Close(gfx);
259        }
260    }
261   
262    NEXUS_PowerManagement_SetCoreState(NEXUS_PowerManagementCore_eGraphics2DMemory, false);
263
264    NEXUS_Module_Destroy(g_NEXUS_graphics2DModule);
265    g_NEXUS_graphics2DModule = NULL;
266}
267
268/****************************************
269* API functions
270***************/
271
272BDBG_OBJECT_ID(NEXUS_Graphics2D);
273
274static NEXUS_Error NEXUS_Graphics2D_P_OpenGrc(unsigned index, const NEXUS_Graphics2DOpenSettings *pSettings)
275{
276    BGRC_Settings grcSettings;
277    int rc;
278    struct NEXUS_Graphics2DEngine *engine = &g_grcInstance[index];
279    NEXUS_HeapHandle heap;
280
281    BGRC_GetDefaultSettings(&grcSettings);
282    grcSettings.ulDeviceNum = index;
283    grcSettings.ulPacketMemoryMax = pSettings->hwFifoSize;
284    heap = NEXUS_P_DefaultHeap(pSettings->heap);
285    if (!heap) heap = g_pCoreHandles->nexusHeap[0];
286    if (!NEXUS_P_CpuAccessibleHeap(heap)) {
287        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
288    }
289    rc = BGRC_Open(&engine->grc, g_pCoreHandles->chp, g_pCoreHandles->reg,
290        NEXUS_Heap_GetMemHandle(heap),
291        g_pCoreHandles->bint, &grcSettings);
292    if (rc) {rc = BERR_TRACE(rc); goto err_opengrc;}
293
294    rc = BKNI_CreateEvent(&engine->advanceEvent);
295    if (rc) {rc = BERR_TRACE(rc); goto err_createevent;}
296
297    engine->advanceEventCallback = NEXUS_RegisterEvent(engine->advanceEvent, NEXUS_Graphics2D_P_PacketAdvance, engine);
298    if (!engine->advanceEventCallback) {rc = BERR_TRACE(-1); goto err_regevent;}
299
300    rc = BGRC_Packet_SetCallback(engine->grc, NEXUS_Graphics2D_PacketCallback_isr, engine);
301    if (rc) {rc = BERR_TRACE(rc); goto err_setcallback;}
302
303    return 0;
304
305err_setcallback:
306    NEXUS_UnregisterEvent(engine->advanceEventCallback);
307err_regevent:
308    BKNI_DestroyEvent(engine->advanceEvent);
309err_createevent:
310    BGRC_Close(engine->grc);
311err_opengrc:
312    return rc;
313}
314
315static void NEXUS_Graphics2D_P_CloseGrc(unsigned index)
316{
317    struct NEXUS_Graphics2DEngine *engine = &g_grcInstance[index];
318
319    if (engine->grc) {
320        BGRC_Close(engine->grc);
321        engine->grc = NULL;
322    }
323    if (engine->advanceEventCallback) {
324        NEXUS_UnregisterEvent(engine->advanceEventCallback);
325    }
326    if (engine->advanceEvent) {
327        BKNI_DestroyEvent(engine->advanceEvent);
328    }
329}
330
331NEXUS_Graphics2DHandle NEXUS_Graphics2D_Open(unsigned index, const NEXUS_Graphics2DOpenSettings *pSettings)
332{
333    NEXUS_Graphics2DHandle gfx;
334    BERR_Code rc;
335    NEXUS_Graphics2DOpenSettings defaultOpenSettings;
336    struct NEXUS_Graphics2DEngine *engine;
337    BGRC_PacketContext_CreateSettings packetContextSettings;
338    NEXUS_HeapHandle heap;
339
340    if (index == NEXUS_ANY_ID) {
341        index = 0;
342    }
343   
344    if (index >= NEXUS_NUM_2D_ENGINES) {
345        BERR_TRACE(NEXUS_INVALID_PARAMETER);
346        return NULL;
347    }
348
349    gfx = BKNI_Malloc(sizeof(*gfx));
350    if(!gfx) {
351        rc = BERR_TRACE(NEXUS_OUT_OF_SYSTEM_MEMORY);
352        return NULL;
353    }
354
355    BKNI_Memset(gfx, 0, sizeof(*gfx));
356    BDBG_OBJECT_SET(gfx, NEXUS_Graphics2D);
357    gfx->settings.colorFormatType = NEXUS_ColorFormatType_eStandardFormat;
358    NEXUS_CALLBACKDESC_INIT(&gfx->settings.checkpointCallback);
359    gfx->settings.pollingCheckpoint = false;
360    gfx->settings.blockedSync = false;
361    gfx->settings.completionTimeout = 0;
362    gfx->index = index;
363
364    if(!pSettings){
365        NEXUS_Graphics2D_GetDefaultOpenSettings(&defaultOpenSettings);
366        pSettings = &defaultOpenSettings;
367    }
368
369    engine = &g_grcInstance[index];
370    if (!BLST_S_FIRST(&engine->contexts)) { 
371        NEXUS_Graphics2D_P_SetPower(gfx, NEXUS_Graphics2DPowerState_ePowerUp);
372        rc = NEXUS_Graphics2D_P_OpenGrc(index, pSettings);
373        NEXUS_Graphics2D_P_SetPower(gfx, NEXUS_Graphics2DPowerState_ePowerDown);
374        if (rc) { rc = BERR_TRACE(rc); goto error; }
375    }
376    BLST_S_INSERT_HEAD(&engine->contexts, gfx, link);
377    gfx->grc = engine->grc;
378
379    /* The nexus packet API requires that BM2MC_PACKET_PixelFormat and NEXUS_PixelFormat must match.
380    There is no conversion function. These CASSERT's help ensure this. nexus_core_convert.c also have ASSERT's. */
381    BDBG_CASSERT(BM2MC_PACKET_PixelFormat_eA8_R8_G8_B8 == (BM2MC_PACKET_PixelFormat)NEXUS_PixelFormat_eA8_R8_G8_B8);
382    BDBG_CASSERT(BM2MC_PACKET_PixelFormat_eCr8_Cb8 == (BM2MC_PACKET_PixelFormat)NEXUS_PixelFormat_eCr8_Cb8);
383    BDBG_CASSERT(BM2MC_PACKET_PixelFormat_eCr10_Y010_Cb10_Y110 == (BM2MC_PACKET_PixelFormat)NEXUS_PixelFormat_eCr10_Y010_Cb10_Y110);
384    BDBG_CASSERT(BM2MC_PACKET_PixelFormat_eMax == (BM2MC_PACKET_PixelFormat)NEXUS_PixelFormat_eR8_G8_B8);
385    BDBG_CASSERT(sizeof(BRect) == sizeof(NEXUS_Rect));
386
387    gfx->openSettings = *pSettings;
388    (void)BGRC_Packet_GetDefaultCreateContextSettings(gfx->grc, &packetContextSettings);
389    if (pSettings->heap) {
390        /* allow null for packet buffer. CPU accessible is only required for GetPacketBuffer, not function-blit. */
391        packetContextSettings.packet_buffer_heap = NEXUS_Heap_GetMemHandle(pSettings->heap);
392    }
393    packetContextSettings.packet_buffer_size = pSettings->packetFifoSize;
394    packetContextSettings.packet_buffer_store = pSettings->packetFifoThreshold;
395    packetContextSettings.private_data = gfx;
396    heap = NEXUS_P_DefaultBoundsHeap(pSettings->boundsHeap);
397    if (heap) {
398        NEXUS_MemoryStatus status;
399        rc = NEXUS_Heap_GetStatus(heap, &status);
400        if (rc) {rc = BERR_TRACE(rc); goto error;}
401        packetContextSettings.memory_bounds.offset = status.offset;
402        packetContextSettings.memory_bounds.size = status.size;
403    }
404    rc = BGRC_Packet_CreateContext( gfx->grc, &gfx->packetContext, &packetContextSettings );
405    if (rc) {rc = BERR_TRACE(rc); goto error;}
406
407    rc = BGRC_Packet_CreateContext( gfx->grc, &gfx->functionContext, &packetContextSettings );
408    if (rc) {rc = BERR_TRACE(rc); goto error;}
409   
410    rc = BGRClib_Open(&gfx->grclib, gfx->grc, gfx->functionContext);
411    if (rc) {rc = BERR_TRACE(rc); goto error;}
412
413    gfx->checkpoint = NEXUS_TaskCallback_Create(gfx, NULL);
414    if(!gfx->checkpoint) { rc = BERR_TRACE(NEXUS_OUT_OF_SYSTEM_MEMORY); goto error; }
415
416    gfx->packetSpaceAvailable = NEXUS_TaskCallback_Create(gfx, NULL);
417    if(!gfx->packetSpaceAvailable) { rc = BERR_TRACE(NEXUS_OUT_OF_SYSTEM_MEMORY); goto error; }
418   
419    /* call timer func once to kick off repeated timer */
420    nexus_graphics2d_p_checkpoint_watchdog(gfx);
421
422    return gfx;
423
424error:
425    NEXUS_Graphics2D_Close(gfx);
426    return NULL;
427}
428
429void NEXUS_Graphics2D_Close(NEXUS_Graphics2DHandle gfx)
430{
431    struct NEXUS_Graphics2DEngine *engine;
432
433    BDBG_OBJECT_ASSERT(gfx, NEXUS_Graphics2D);
434    engine = &g_grcInstance[gfx->index];
435
436    if (gfx->grclib) {
437        BGRClib_Close(gfx->grclib);
438    }
439    if (gfx->functionContext) {
440        BGRC_Packet_DestroyContext( gfx->grc, gfx->functionContext );
441    }
442    if (gfx->packetContext) {
443        BGRC_Packet_DestroyContext( gfx->grc, gfx->packetContext );
444    }
445
446    if (gfx->grc) {
447        BLST_S_REMOVE(&engine->contexts, gfx, NEXUS_Graphics2D, link);
448        if (!BLST_S_FIRST(&engine->contexts)) {
449            NEXUS_Graphics2D_P_SetPower(gfx, NEXUS_Graphics2DPowerState_ePowerUp);
450            NEXUS_Graphics2D_P_CloseGrc(gfx->index);
451            /* this powers down unconditionally, even if the last blit didn't have a checkpoint */
452            NEXUS_Graphics2D_P_SetPower(gfx, NEXUS_Graphics2DPowerState_ePowerDown);   
453        }
454    }
455
456    if(gfx->checkpoint) {
457        NEXUS_TaskCallback_Destroy(gfx->checkpoint);
458    }
459    if(gfx->packetSpaceAvailable) {
460        NEXUS_TaskCallback_Destroy(gfx->packetSpaceAvailable);
461    }
462    if (gfx->checkpointWatchdog.timer) {
463        NEXUS_CancelTimer(gfx->checkpointWatchdog.timer);
464    }
465
466    BDBG_OBJECT_DESTROY(gfx, NEXUS_Graphics2D);
467    BKNI_Free(gfx);
468}
469
470void NEXUS_Graphics2D_GetDefaultOpenSettings(NEXUS_Graphics2DOpenSettings *pSettings)
471{
472    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
473    pSettings->hwFifoSize = 128*1024;
474    pSettings->packetFifoSize = 128*1024;
475    pSettings->packetFifoThreshold = pSettings->packetFifoSize; /* maximum throughput */
476}
477
478void NEXUS_Graphics2D_GetSettings(NEXUS_Graphics2DHandle gfx, NEXUS_Graphics2DSettings *pSettings)
479{
480    BDBG_OBJECT_ASSERT(gfx, NEXUS_Graphics2D);
481    *pSettings = gfx->settings;
482}
483
484NEXUS_Error NEXUS_Graphics2D_SetSettings(NEXUS_Graphics2DHandle gfx, const NEXUS_Graphics2DSettings *pSettings)
485{
486    BDBG_OBJECT_ASSERT(gfx, NEXUS_Graphics2D);
487    if (pSettings->blockedSync) {
488        /* Converting your app to not used blockedSync is easy. And, you then have an opportunity to get much better performance
489        by queueing multiple async blits without having the overhead of interrupts and checkpoints on each one.
490        See the NEXUS_Graphics2D_Checkpoint logic in nexus/examples/graphics for sample code. */
491        BDBG_ERR(("blockedSync is not supported"));
492        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
493    }
494    gfx->settings = *pSettings;
495    NEXUS_TaskCallback_Set(gfx->checkpoint, &gfx->settings.checkpointCallback);
496    NEXUS_TaskCallback_Set(gfx->packetSpaceAvailable, &gfx->settings.packetSpaceAvailable);
497    return NEXUS_SUCCESS;
498}
499
500void NEXUS_Graphics2D_GetDefaultFillSettings(NEXUS_Graphics2DFillSettings *pSettings)
501{
502    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
503    pSettings->colorOp = NEXUS_FillOp_eCopy;
504    pSettings->alphaOp = NEXUS_FillOp_eCopy;
505}
506
507void NEXUS_Graphics2D_GetDefaultPorterDuffFillSettings(NEXUS_Graphics2DPorterDuffFillSettings *pSettings)
508{
509    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
510}
511
512static NEXUS_Error
513NEXUS_Graphics2D_P_FinishOperation(NEXUS_Graphics2DHandle gfx, BERR_Code rc)
514{
515    /* if there's a threshold, then a */
516    if (gfx->openSettings.packetFifoThreshold && !gfx->checkpointWatchdog.counter) {
517        gfx->checkpointWatchdog.counter = 2; /* wait between 5 and 10 seconds */
518    }
519    if (rc==BERR_SUCCESS) {
520        return NEXUS_SUCCESS;
521    }
522    else if (rc == BERR_OUT_OF_SYSTEM_MEMORY || rc == BERR_OUT_OF_DEVICE_MEMORY) {
523        BDBG_MSG(("Blitter SW fifo is full. Increase NEXUS_Graphics2DOpenSettings.packetBufferSize or wait for packetSpaceAvailable."));
524        gfx->packetSpaceAvailableCount++;
525        return NEXUS_GRAPHICS2D_QUEUE_FULL; /* not an error */
526    }
527    else {
528        return BERR_TRACE(rc);
529    }
530}
531
532/* convert pixel from surface's pixel format to universal ARGB or YCrCb which M2MC HW understands */
533static uint32_t NEXUS_Graphics2D_P_ConvertPixel(NEXUS_PixelFormat format, uint32_t pixel)
534{
535    /* BPXL_ConvertPixel has the logic for this. It's not efficient, but we would have to duplicate BPXL logic. */
536    uint32_t ulColor = 0;
537    BPXL_Format srcformat;
538    if (!NEXUS_P_PixelFormat_ToMagnum(format, &srcformat)) {
539        BPXL_Format dstformat = NEXUS_PIXEL_FORMAT_IS_YCRCB(format) ? BPXL_eA8_Y8_Cb8_Cr8 : BPXL_eA8_R8_G8_B8;
540        BPXL_ConvertPixel( dstformat, srcformat, pixel, (unsigned int *) &ulColor );
541    }
542    return ulColor;   
543}
544
545NEXUS_Error NEXUS_Graphics2D_Fill(NEXUS_Graphics2DHandle gfx, const NEXUS_Graphics2DFillSettings *pSettings)
546{
547    BERR_Code rc;
548    BM2MC_PACKET_Plane surface;
549    BGRCLib_FillOp colorOp, alphaOp;
550    unsigned srcPaletteOffset;
551    uint32_t color;
552
553    BDBG_CASSERT((NEXUS_FillOp_eMax - 2) == (NEXUS_FillOp)BGRCLib_FillOp_eBlend); /* skip over NEXUS_FillOp_eUseBlendEquation */
554    BDBG_OBJECT_ASSERT(gfx, NEXUS_Graphics2D);
555   
556    if (pSettings->colorOp == NEXUS_FillOp_eUseBlendEquation ||
557        pSettings->alphaOp == NEXUS_FillOp_eUseBlendEquation)
558    {
559        NEXUS_Graphics2DBlitSettings blitSettings;
560        static const NEXUS_BlendEquation g_copyEq = {NEXUS_BlendFactor_eConstantColor, NEXUS_BlendFactor_eOne, false,
561            NEXUS_BlendFactor_eZero, NEXUS_BlendFactor_eZero, false, NEXUS_BlendFactor_eZero};
562        static const NEXUS_BlendEquation g_blendEq = {NEXUS_BlendFactor_eConstantColor, NEXUS_BlendFactor_eConstantAlpha, false,
563            NEXUS_BlendFactor_eSourceColor, NEXUS_BlendFactor_eInverseConstantAlpha, false, NEXUS_BlendFactor_eZero};
564        static const NEXUS_BlendEquation g_copyAlphaEq = {NEXUS_BlendFactor_eConstantAlpha, NEXUS_BlendFactor_eOne, false,
565            NEXUS_BlendFactor_eZero, NEXUS_BlendFactor_eZero, false, NEXUS_BlendFactor_eZero};
566
567        NEXUS_Graphics2D_GetDefaultBlitSettings(&blitSettings);
568        blitSettings.source.surface = pSettings->surface;
569        blitSettings.source.rect = pSettings->rect;
570        blitSettings.dest.surface = pSettings->surface;
571        blitSettings.dest.rect = pSettings->rect;
572        blitSettings.output.surface = pSettings->surface;
573        blitSettings.output.rect = pSettings->rect;
574        blitSettings.constantColor = pSettings->color;
575        switch (pSettings->colorOp) {
576        case NEXUS_FillOp_eIgnore:
577            blitSettings.colorOp = NEXUS_BlitColorOp_eCopySource;
578            break;
579        case NEXUS_FillOp_eCopy:
580            blitSettings.colorOp = NEXUS_BlitColorOp_eUseBlendEquation;
581            blitSettings.colorBlend = g_copyEq;
582            break;
583        case NEXUS_FillOp_eBlend:
584            blitSettings.colorOp = NEXUS_BlitColorOp_eUseBlendEquation;
585            blitSettings.colorBlend = g_blendEq;
586            break;
587        case NEXUS_FillOp_eUseBlendEquation:
588            blitSettings.colorOp = NEXUS_BlitColorOp_eUseBlendEquation;
589            blitSettings.colorBlend = pSettings->colorBlend;
590            break;
591        default:
592            return BERR_TRACE(NEXUS_INVALID_PARAMETER);
593        }
594        switch (pSettings->alphaOp) {
595        case NEXUS_FillOp_eIgnore:
596            blitSettings.alphaOp = NEXUS_BlitAlphaOp_eCopySource;
597            break;
598        case NEXUS_FillOp_eCopy:
599            blitSettings.alphaOp = NEXUS_BlitAlphaOp_eUseBlendEquation;
600            blitSettings.alphaBlend = g_copyAlphaEq;
601            break;
602        case NEXUS_FillOp_eUseBlendEquation:
603            blitSettings.alphaOp = NEXUS_BlitAlphaOp_eUseBlendEquation;
604            blitSettings.alphaBlend = pSettings->alphaBlend;
605            break;
606        case NEXUS_FillOp_eBlend:
607        default:
608            return BERR_TRACE(NEXUS_INVALID_PARAMETER);
609        }
610        return NEXUS_Graphics2D_Blit(gfx, &blitSettings);
611    }
612
613    BTRC_TRACE(nexus_graphics2d_blit, START);
614    colorOp = pSettings->colorOp;
615    alphaOp = pSettings->alphaOp;
616
617    NEXUS_Module_Lock( g_NEXUS_graphics2DData.settings.surface );
618    NEXUS_Surface_InitPlane_priv(pSettings->surface, &surface, &srcPaletteOffset);
619    NEXUS_Module_Unlock( g_NEXUS_graphics2DData.settings.surface );
620
621    BDBG_PRINT_OP(("fill %#x(%u,%u,%u,%u) pixel=%#x %u,%u", (unsigned)pSettings->surface, 
622        pSettings->rect.x, pSettings->rect.y, pSettings->rect.width, pSettings->rect.height,
623        pSettings->color, pSettings->colorOp, pSettings->alphaOp));
624
625    NEXUS_Graphics2D_P_SetPower(gfx, NEXUS_Graphics2DPowerState_ePowerUp);
626
627    if (gfx->settings.colorFormatType == NEXUS_ColorFormatType_eSameAsSurface || srcPaletteOffset) {
628        color = NEXUS_Graphics2D_P_ConvertPixel(surface.format, pSettings->color);
629    }
630    else {
631        color = pSettings->color;
632    }
633   
634    rc = BGRClib_Blended_Fill(gfx->grclib,
635        &surface,
636        color,
637        (const BRect *)(void*)&pSettings->rect,
638        colorOp,
639        alphaOp);
640    BTRC_TRACE(nexus_graphics2d_blit, STOP);
641    return NEXUS_Graphics2D_P_FinishOperation(gfx, rc);
642}
643
644NEXUS_Error NEXUS_Graphics2D_PorterDuffFill(NEXUS_Graphics2DHandle gfx, const NEXUS_Graphics2DPorterDuffFillSettings *pSettings)
645{
646    BERR_Code rc;
647    BM2MC_PACKET_Plane surface;
648    unsigned srcPaletteOffset;
649    uint32_t color;
650
651    BTRC_TRACE(nexus_graphics2d_blit, START);
652
653    BDBG_OBJECT_ASSERT(gfx, NEXUS_Graphics2D);
654    NEXUS_Module_Lock( g_NEXUS_graphics2DData.settings.surface );
655    NEXUS_Surface_InitPlane_priv(pSettings->surface, &surface, &srcPaletteOffset);
656    NEXUS_Module_Unlock( g_NEXUS_graphics2DData.settings.surface );
657
658    BDBG_PRINT_OP(("Porter Duff fill %#x(%u,%u,%u,%u) pixel=%#x op=%u", (unsigned)pSettings->surface, 
659        pSettings->rect.x, pSettings->rect.y, pSettings->rect.width, pSettings->rect.height,
660        pSettings->color, pSettings->operation));
661
662    NEXUS_Graphics2D_P_SetPower(gfx, NEXUS_Graphics2DPowerState_ePowerUp);
663
664    if (gfx->settings.colorFormatType == NEXUS_ColorFormatType_eSameAsSurface || srcPaletteOffset) {
665        color = NEXUS_Graphics2D_P_ConvertPixel(surface.format, pSettings->color);
666    }
667    else {
668        color = pSettings->color;
669    }
670   
671    rc = BGRClib_PorterDuffFill(gfx->grclib,
672        (BGRCLib_PorterDuffOp)pSettings->operation,
673        &surface,
674        color,
675        (const BRect *)(void*)&pSettings->rect);
676    BTRC_TRACE(nexus_graphics2d_blit, STOP);
677    return NEXUS_Graphics2D_P_FinishOperation(gfx, rc);
678}
679
680void NEXUS_Graphics2D_GetDefaultBlitSettings(NEXUS_Graphics2DBlitSettings *pSettings )
681{
682    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
683    pSettings->horizontalFilter = NEXUS_Graphics2DFilterCoeffs_eAnisotropic;
684    pSettings->verticalFilter = NEXUS_Graphics2DFilterCoeffs_eAnisotropic;
685    pSettings->constantColor = 0xFF000000; /* match GRClib */
686    /* don't default dest and source constant color. rarely used and user must set. */
687}
688
689/***************************************************************************
690Description:
691    RGB to YCbCr color matrix table.
692    Taken from rockford/applications/bmetest/grc_test/bgfx_blit.c
693****************************************************************************/
694/* Y  = R *  0.257 + G *  0.504 + B *  0.098 + 16  */
695/* Cb = R * -0.148 + G * -0.291 + B *  0.439 + 128 */
696/* Cr = R *  0.439 + G * -0.368 + B * -0.071 + 128 */
697static const int32_t g_NEXUS_ai32_Matrix_RGBtoYCbCr[20] =
698{
699    (int32_t) ( 0.257f * (1 << 10)),   /*  R factor for Y */
700    (int32_t) ( 0.504f * (1 << 10)),   /*  G factor for Y */
701    (int32_t) ( 0.098f * (1 << 10)),   /*  B factor for Y */
702    (int32_t) 0,                       /*  A factor for Y */
703    (int32_t) (16 * (1 << 10)),        /* Increment for Y */
704    (int32_t) (-0.148f * (1 << 10)),   /*  R factor for Cb */
705    (int32_t) (-0.291f * (1 << 10)),   /*  G factor for Cb */
706    (int32_t) ( 0.439f * (1 << 10)),   /*  B factor for Cb */
707    (int32_t) 0,                       /*  A factor for Cb */
708    (int32_t) (128 * (1 << 10)),       /* Increment for Cb */
709    (int32_t) ( 0.439f * (1 << 10)),   /*  R factor for Cr */
710    (int32_t) (-0.368f * (1 << 10)),   /*  G factor for Cr */
711    (int32_t) (-0.071f * (1 << 10)),   /*  B factor for Cr */
712    (int32_t) 0,                       /*  A factor for Cr */
713    (int32_t) (128 * (1 << 10)),       /* Increment for Cr */
714    (int32_t) 0,                       /*  R factor for A */
715    (int32_t) 0,                       /*  G factor for A */
716    (int32_t) 0,                       /*  B factor for A */
717    (int32_t) (1 << 10),               /*  A factor for A */
718    (int32_t) 0,                       /* Increment for A */
719};
720
721/***************************************************************************
722Description:
723    YCbCr to RGB color matrix table.
724    Taken from rockford/applications/bmetest/grc_test/bgfx_blit.c
725****************************************************************************/
726/* R = Y * 1.164 + Cr * 1.596 - 223 */
727/* G = Y * 1.164 - Cr * 0.813 - Cb * 0.391 + 135 */
728/* B = Y * 1.164 + Cb * 2.018 - 277 */
729const int32_t g_NEXUS_ai32_Matrix_YCbCrtoRGB[20] =
730{
731    (int32_t) ( 1.164f * (1 << 10)),   /*  Y factor for R */
732    (int32_t) 0,                       /* Cb factor for R */
733    (int32_t) ( 1.596f * (1 << 10)),   /* Cr factor for R */
734    (int32_t) 0,                       /*  A factor for R */
735    (int32_t) (-223 * (1 << 10)),      /* Increment for R */
736    (int32_t) ( 1.164f * (1 << 10)),   /*  Y factor for G */
737    (int32_t) (-0.391f * (1 << 10)),   /* Cb factor for G */
738    (int32_t) (-0.813f * (1 << 10)),   /* Cr factor for G */
739    (int32_t) 0,                       /*  A factor for G */
740    (int32_t) (134 * (1 << 10)),       /* Increment for G */
741    (int32_t) ( 1.164f * (1 << 10)),   /*  Y factor for B */
742    (int32_t) ( 2.018f * (1 << 10)),   /* Cb factor for B */
743    (int32_t) 0,                       /* Cr factor for B */
744    (int32_t) 0,                       /*  A factor for B */
745    (int32_t) (-277 * (1 << 10)),      /* Increment for B */
746    (int32_t) 0,                       /*  Y factor for A */
747    (int32_t) 0,                       /* Cb factor for A */
748    (int32_t) 0,                       /* Cr factor for A */
749    (int32_t) (1 << 10),               /*  A factor for A */
750    (int32_t) 0,                       /* Increment for A */
751};
752
753static void NEXUS_P_CopyBlendEq(BGRClib_BlendEquation *dst, const void *src)
754{
755    *dst = *((BGRClib_BlendEquation *)src);
756    return;
757}
758#define NEXUS_P_COPYBLENDEQ(dst,src) NEXUS_P_CopyBlendEq(dst, src)
759
760NEXUS_Error NEXUS_Graphics2D_Blit(NEXUS_Graphics2DHandle gfx, const NEXUS_Graphics2DBlitSettings*  pSettings)
761{
762    BERR_Code rc;
763    BGRClib_BlitColorKeyParams *pColorKeyParams = NULL;
764    BGRClib_BlitMatrixParams *pMatrixParams = NULL;
765    BGRClib_BlitPatternParams *pPatternParams = NULL;
766    BGRClib_BlitScalingControlParams *pScalingControlParams = NULL;
767    BM2MC_PACKET_Plane src, dst, out;
768    unsigned srcPaletteOffset, dstPaletteOffset = 0, outPaletteOffset;
769    BGRCLib_BlitColorOp colorOp;
770    BGRCLib_BlitAlphaOp alphaOp;
771    uint32_t constantColor = pSettings->constantColor;
772
773    BTRC_TRACE(nexus_graphics2d_blit, START);
774
775#if 0
776    BKNI_Printf("NEXUS_Graphics2D_Blit\n"
777        "  source %p, %d,%d,%d,%d\n"
778        "  dest   %p, %d,%d,%d,%d\n"
779        "  output %p, %d,%d,%d,%d\n"
780        "  colorop %d, alphaop %d, constant %08x\n"
781        "  enabled %d %d %d %d\n"
782        "  horiz %d, vert %d\n"
783        "  enabled %d %d %d %d %d %d\n",
784        pSettings->source.surface, pSettings->source.rect.x, pSettings->source.rect.y, pSettings->source.rect.width, pSettings->source.rect.height,
785        pSettings->dest.surface, pSettings->dest.rect.x, pSettings->dest.rect.y, pSettings->dest.rect.width, pSettings->dest.rect.height,
786        pSettings->output.surface, pSettings->output.rect.x, pSettings->output.rect.y, pSettings->output.rect.width, pSettings->output.rect.height,
787        pSettings->colorOp, pSettings->alphaOp, pSettings->constantColor,
788        pSettings->colorKey.source.enabled, pSettings->colorKey.dest.enabled, pSettings->conversionMatrixEnabled, pSettings->patternSettingsEnabled,
789        pSettings->horizontalFilter, pSettings->verticalFilter,
790        pSettings->scalingControlSettingsEnabled, pSettings->mirrorSourceVertically, pSettings->mirrorSourceHorizontally, pSettings->mirrorDestVertically, pSettings->mirrorDestHorizontally, pSettings->alphaPremultiplySourceEnabled);
791#endif
792
793    BDBG_OBJECT_ASSERT(gfx, NEXUS_Graphics2D);
794
795    /* copy surfaces */
796    NEXUS_Module_Lock( g_NEXUS_graphics2DData.settings.surface );
797    NEXUS_Surface_InitPlane_priv(pSettings->source.surface, &src, &srcPaletteOffset);
798    if (pSettings->dest.surface) {
799        NEXUS_Surface_InitPlane_priv(pSettings->dest.surface, &dst, &dstPaletteOffset);
800    }
801    NEXUS_Surface_InitPlane_priv(pSettings->output.surface, &out, &outPaletteOffset);
802    NEXUS_Module_Unlock( g_NEXUS_graphics2DData.settings.surface );
803
804    if (!srcPaletteOffset && outPaletteOffset) {
805        BDBG_ERR(("Cannot blit from non-palette to palette."));
806        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
807    }
808
809    /* prep blitParams here so we can start setting it up in the switch statements */
810    if (srcPaletteOffset) {
811        BGRClib_GetDefaultPaletteBlitParams(&gfx->blitData.blitParams);
812        if (pSettings->horizontalFilter != NEXUS_Graphics2DFilterCoeffs_ePointSample ||
813            pSettings->verticalFilter != NEXUS_Graphics2DFilterCoeffs_ePointSample) {
814            BDBG_WRN(("Current filter type will cause color noise in scale-up"));
815        }
816    } else {
817        BGRClib_GetDefaultBlitParams(&gfx->blitData.blitParams);
818    }
819
820    switch (pSettings->colorOp) {
821    case NEXUS_BlitColorOp_eCopySource:
822        colorOp = BGRCLib_BlitColorOp_eCopySource;
823        break;
824    case NEXUS_BlitColorOp_eUseConstantAlpha:
825        /* this does not require dest. if no dest, source will be multiplied (i.e. reduced) with the constant alpha */
826        colorOp = BGRCLib_BlitColorOp_eUseConstantAlpha;
827        break;
828    case NEXUS_BlitColorOp_eUseSourceAlpha:
829        /* this does not require dest. if no dest, source will be multiplied (i.e. reduced) with its own alpha (i.e. self reducing) */
830        colorOp = BGRCLib_BlitColorOp_eUseSourceAlpha;
831        break;
832    case NEXUS_BlitColorOp_eUseDestAlpha:
833        if (!pSettings->dest.surface) {
834            return BERR_TRACE(NEXUS_INVALID_PARAMETER);
835        }
836        colorOp = BGRCLib_BlitColorOp_eUseDestAlpha;
837        break;
838    case NEXUS_BlitColorOp_eSelectPaletteWithColorkey:
839        colorOp = BGRCLib_BlitColorOp_eSelectPaletteWithColorkey;
840        break;
841    case NEXUS_BlitColorOp_eAdd:
842        if (!pSettings->dest.surface) {
843            return BERR_TRACE(NEXUS_INVALID_PARAMETER);
844        }
845        colorOp = BGRCLib_BlitColorOp_eAdd;
846        break;
847    case NEXUS_BlitColorOp_eUseBlendEquation:
848        colorOp = BGRCLib_BlitColorOp_eUseBlendFactors;
849        BDBG_CASSERT((NEXUS_BlendFactor_eMax-1) == (NEXUS_BlendFactor)BGRC_Blend_Source_eInverseConstantAlpha);
850        BDBG_CASSERT(sizeof(gfx->blitData.blitParams.colorBlend) == sizeof(pSettings->colorBlend));
851        NEXUS_P_COPYBLENDEQ(&gfx->blitData.blitParams.colorBlend, &pSettings->colorBlend);
852        break;
853    default:
854        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
855    }
856
857    switch (pSettings->alphaOp) {
858    case NEXUS_BlitAlphaOp_eCopySource:
859        alphaOp = BGRCLib_BlitAlphaOp_eCopySource;
860        {
861            /* loop up pixel format info, but only when needed */
862            const NEXUS_PixelFormatInfo *pSourcePixelFormatInfo = NEXUS_PixelFormat_GetInfo(src.format);
863            if (!pSourcePixelFormatInfo->alpha_per_pixel && !srcPaletteOffset) {
864                if (pSettings->colorOp == NEXUS_BlitColorOp_eUseConstantAlpha) {
865                    BDBG_ERR(("Incompatible colorOp and alphaOp settings for this blit. Use NEXUS_BlitAlphaOp_eCopyDest or eCopyConstant."));
866                    return BERR_TRACE(NEXUS_INVALID_PARAMETER);
867                }
868                alphaOp = BGRCLib_BlitAlphaOp_eUseConstAlpha;
869                constantColor = 0xFF000000;
870            }
871        }
872        break;
873    case NEXUS_BlitAlphaOp_eCopyDest:
874        if (!pSettings->dest.surface) {
875            return BERR_TRACE(NEXUS_INVALID_PARAMETER);
876        }
877        alphaOp = BGRCLib_BlitAlphaOp_eUseDestAlpha;
878        {
879            /* loop up pixel format info, but only when needed */
880            const NEXUS_PixelFormatInfo *pDestPixelFormatInfo = NEXUS_PixelFormat_GetInfo(dst.format);
881            if (!pDestPixelFormatInfo->alpha_per_pixel && !dstPaletteOffset) {
882                if (pSettings->colorOp == NEXUS_BlitColorOp_eUseConstantAlpha) {
883                    BDBG_ERR(("Incompatible colorOp and alphaOp settings for this blit. Use NEXUS_BlitAlphaOp_eCopySource or eCopyConstant."));
884                    return BERR_TRACE(NEXUS_INVALID_PARAMETER);
885                }
886                alphaOp = BGRCLib_BlitAlphaOp_eUseConstAlpha;
887                constantColor = 0xFF000000;
888            }
889        }
890        break;
891    case NEXUS_BlitAlphaOp_eCopyConstant:
892        alphaOp = BGRCLib_BlitAlphaOp_eUseConstAlpha;
893        break;
894    case NEXUS_BlitAlphaOp_eCombine:
895        alphaOp = BGRCLib_BlitAlphaOp_eUseCombinedAlpha;
896        break;
897    case NEXUS_BlitAlphaOp_eEmulateTransparentVideo:
898        alphaOp = BGRCLib_BlitAlphaOp_eEmulateTransparentVideo;
899        break;
900    case NEXUS_BlitAlphaOp_eAdd:
901        alphaOp = BGRCLib_BlitAlphaOp_eAdd;
902        break;
903    case NEXUS_BlitAlphaOp_eUseBlendEquation:
904        alphaOp = BGRCLib_BlitAlphaOp_eUseBlendFactors;
905        BDBG_CASSERT(sizeof(gfx->blitData.blitParams.alphaBlend) == sizeof(pSettings->alphaBlend));
906        NEXUS_P_COPYBLENDEQ(&gfx->blitData.blitParams.alphaBlend, &pSettings->alphaBlend);
907        break;
908    default:
909        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
910    }
911
912    gfx->blitData.blitParams.srcSurface = &src;
913    gfx->blitData.blitParams.srcRect = (const BRect *)(void*)&pSettings->source.rect;
914    gfx->blitData.blitParams.srcPaletteOffset = srcPaletteOffset; 
915    gfx->blitData.blitParams.dstSurface = pSettings->dest.surface?&dst:NULL;
916    gfx->blitData.blitParams.dstRect = (const BRect *)(void*)&pSettings->dest.rect;
917    gfx->blitData.blitParams.outSurface = &out;
918    gfx->blitData.blitParams.outRect = (const BRect *)(void*)&pSettings->output.rect;
919    gfx->blitData.blitParams.colorOp = colorOp;
920    gfx->blitData.blitParams.alphaOp = alphaOp;
921    gfx->blitData.blitParams.constantColor = constantColor; /* blend constant color */
922    if (pSettings->useDestAndSourceConstantColor) {
923        gfx->blitData.blitParams.destConstantColor = pSettings->destConstantColor;
924        gfx->blitData.blitParams.sourceConstantColor = pSettings->sourceConstantColor;
925    }
926    else {
927        gfx->blitData.blitParams.destConstantColor = constantColor;
928        gfx->blitData.blitParams.sourceConstantColor = constantColor;
929    }
930    gfx->blitData.blitParams.colorKeySelect = BGRC_Output_ColorKeySelection_eTakeBlend;
931   
932    /* copy mirror flags */
933    gfx->blitData.blitParams.mirrorSrcVertically = pSettings->mirrorSourceVertically;
934    gfx->blitData.blitParams.mirrorSrcHorizontally = pSettings->mirrorSourceHorizontally;
935    gfx->blitData.blitParams.mirrorDstVertically = pSettings->mirrorDestVertically;
936    gfx->blitData.blitParams.mirrorDstHorizontally = pSettings->mirrorDestHorizontally;
937    /* auto-mirror if the output overlaps the source. */
938    if (pSettings->source.surface == pSettings->output.surface) { 
939        if (pSettings->output.rect.y > pSettings->source.rect.y && !gfx->blitData.blitParams.mirrorSrcVertically && !gfx->blitData.blitParams.mirrorDstVertically) {
940            gfx->blitData.blitParams.mirrorSrcVertically = true;
941            gfx->blitData.blitParams.mirrorDstVertically = true;
942        }
943        if (pSettings->output.rect.x > pSettings->source.rect.x && !gfx->blitData.blitParams.mirrorSrcHorizontally && !gfx->blitData.blitParams.mirrorDstHorizontally) {
944            gfx->blitData.blitParams.mirrorSrcHorizontally = true;
945            gfx->blitData.blitParams.mirrorDstHorizontally = true;
946        }
947    }   
948   
949    gfx->blitData.blitParams.srcAlphaPremult = pSettings->alphaPremultiplySourceEnabled;
950
951    if (pSettings->colorKey.source.enabled || pSettings->colorKey.dest.enabled) {
952        BGRClib_GetDefaultColorKeyParams(&gfx->blitData.colorKeyParams);
953        /* Use the output of the blend block instead of the source if any form of blending is required */
954        if ( (pSettings->colorOp != NEXUS_BlitColorOp_eCopySource &&
955              pSettings->colorOp != NEXUS_BlitColorOp_eSelectPaletteWithColorkey) ||
956              pSettings->alphaOp != NEXUS_BlitAlphaOp_eCopySource ) {
957            gfx->blitData.colorKeyParams.cksOnlyDstColorKeyed = BGRC_Output_ColorKeySelection_eTakeBlend;
958        }
959        gfx->blitData.colorKeyParams.enableColorKey = pSettings->colorKey.source.enabled;
960        gfx->blitData.colorKeyParams.enableDstColorKey = pSettings->colorKey.dest.enabled;
961        /* GRClib's colorKeySelect is derived from other params */
962        if (pSettings->colorKey.dest.enabled) {
963            /* if dest.enabled then we eTakeDestination. if there's a dest surface, we take that. if not, we take dest constant color. */
964            gfx->blitData.blitParams.colorKeySelect = BGRC_Output_ColorKeySelection_eTakeDestination;
965        }
966
967        gfx->blitData.colorKeyParams.colorKeyLower = pSettings->colorKey.source.lower;
968        gfx->blitData.colorKeyParams.colorKeyUpper = pSettings->colorKey.source.upper;
969        gfx->blitData.colorKeyParams.colorKeyMask = pSettings->colorKey.source.mask;
970        gfx->blitData.colorKeyParams.colorKeyReplace = pSettings->colorKey.source.replace;
971        gfx->blitData.colorKeyParams.colorKeyRplMask = pSettings->colorKey.source.replaceMask;
972        gfx->blitData.colorKeyParams.dstColorKeyLower = pSettings->colorKey.dest.lower;
973        gfx->blitData.colorKeyParams.dstColorKeyUpper = pSettings->colorKey.dest.upper;
974        gfx->blitData.colorKeyParams.dstColorKeyMask = pSettings->colorKey.dest.mask;
975        gfx->blitData.colorKeyParams.dstColorKeyReplace = pSettings->colorKey.dest.replace;
976        gfx->blitData.colorKeyParams.dstColorKeyRplMask = pSettings->colorKey.dest.replaceMask;
977
978        pColorKeyParams = &gfx->blitData.colorKeyParams;
979    }
980
981    if (pSettings->conversionMatrixEnabled) {
982        gfx->blitData.matrixParams.conversionMatrix = (int32_t *)pSettings->conversionMatrix.coeffMatrix;
983        gfx->blitData.matrixParams.matrixShift = pSettings->conversionMatrix.shift;
984        pMatrixParams = &gfx->blitData.matrixParams;
985    }
986    else {
987        bool sourceYCrCb, outputYCrCb;
988
989        if (srcPaletteOffset) {
990            NEXUS_SurfaceCreateSettings createSettings;
991            NEXUS_Surface_GetCreateSettings(pSettings->source.surface, &createSettings);
992            sourceYCrCb = NEXUS_PIXEL_FORMAT_IS_YCRCB(createSettings.palettePixelFormat);
993        }
994        else {
995            sourceYCrCb = NEXUS_PIXEL_FORMAT_IS_YCRCB(src.format);
996        }
997        if (outPaletteOffset) {
998            NEXUS_SurfaceCreateSettings createSettings;
999            NEXUS_Surface_GetCreateSettings(pSettings->output.surface, &createSettings);
1000            outputYCrCb = NEXUS_PIXEL_FORMAT_IS_YCRCB(createSettings.palettePixelFormat);
1001        }
1002        else {
1003            outputYCrCb = NEXUS_PIXEL_FORMAT_IS_YCRCB(out.format);
1004        }
1005
1006        /* TODO: handle both flavors of YCrCb */
1007        if (sourceYCrCb && !outputYCrCb) {
1008            BDBG_MSG(("YCrCb->RGB conversion"));
1009            gfx->blitData.matrixParams.conversionMatrix = (int32_t *)g_NEXUS_ai32_Matrix_YCbCrtoRGB;
1010            gfx->blitData.matrixParams.matrixShift = 10;
1011            pMatrixParams = &gfx->blitData.matrixParams;
1012        }
1013        else if (!sourceYCrCb && outputYCrCb) {
1014            BDBG_MSG(("RGB->YCrCb conversion"));
1015            gfx->blitData.matrixParams.conversionMatrix = (int32_t *)g_NEXUS_ai32_Matrix_RGBtoYCbCr;
1016            gfx->blitData.matrixParams.matrixShift = 10;
1017            pMatrixParams = &gfx->blitData.matrixParams;
1018        }
1019    }
1020
1021    if (pSettings->patternSettingsEnabled) {
1022        gfx->blitData.blitParams.colorKeySelect = BGRC_Output_ColorKeySelection_eTakePattern;
1023        gfx->blitData.patternParams.ropVector = pSettings->patternSettings.ropVector;
1024        gfx->blitData.patternParams.pattern = (uint8_t *)pSettings->patternSettings.pattern;
1025        gfx->blitData.patternParams.foreColor = pSettings->patternSettings.foreColor;
1026        gfx->blitData.patternParams.backColor = pSettings->patternSettings.backColor;
1027        pPatternParams = &gfx->blitData.patternParams;
1028    }
1029
1030    if (pSettings->scalingControlSettingsEnabled) {
1031        BDBG_CASSERT(sizeof(gfx->blitData.scalingControlParams) == sizeof(pSettings->scalingControlSettings));
1032        BKNI_Memcpy(&gfx->blitData.scalingControlParams, &pSettings->scalingControlSettings, sizeof(gfx->blitData.scalingControlParams));;
1033        pScalingControlParams = &gfx->blitData.scalingControlParams;
1034    }
1035
1036    BDBG_CASSERT(NEXUS_Graphics2DFilterCoeffs_eAntiFlutterSharp == (NEXUS_Graphics2DFilterCoeffs)BGRC_FilterCoeffs_eAntiFlutterSharp);
1037    gfx->blitData.blitParams.horzFilter = pSettings->horizontalFilter;
1038    gfx->blitData.blitParams.vertFilter = pSettings->verticalFilter;
1039   
1040    NEXUS_Graphics2D_P_SetPower(gfx, NEXUS_Graphics2DPowerState_ePowerUp);
1041
1042    if(pSettings->colorOp==NEXUS_BlitColorOp_eUseBlendEquation) {
1043        BDBG_PRINT_OP(("blit colorBlend a=%u b=%u %c c=%u d=%u %c e=%u", pSettings->colorBlend.a, pSettings->colorBlend.b, pSettings->colorBlend.subtract_cd?'-':'+', pSettings->colorBlend.c, pSettings->colorBlend.d, pSettings->colorBlend.subtract_e?'-':'+', pSettings->colorBlend.e));
1044    }
1045    if(pSettings->alphaOp==NEXUS_BlitAlphaOp_eUseBlendEquation) {
1046        BDBG_PRINT_OP(("blit alphaBlend a=%u b=%u %c c=%u d=%u %c e=%u", pSettings->alphaBlend.a, pSettings->alphaBlend.b, pSettings->alphaBlend.subtract_cd?'-':'+', pSettings->alphaBlend.c, pSettings->alphaBlend.d, pSettings->alphaBlend.subtract_e?'-':'+', pSettings->alphaBlend.e));
1047    }
1048    BDBG_PRINT_OP(("blit source=%#x(%u,%u,%u,%u) output=%#x(%u,%u,%u,%u) dest=%#x(%u,%u,%u,%u) ops=%u,%u",
1049        (unsigned)pSettings->source.surface,
1050        pSettings->source.rect.x, pSettings->source.rect.y, pSettings->source.rect.width, pSettings->source.rect.height,
1051        (unsigned)pSettings->output.surface, 
1052        pSettings->output.rect.x, pSettings->output.rect.y, pSettings->output.rect.width, pSettings->output.rect.height,
1053        (unsigned)pSettings->dest.surface,   
1054        pSettings->source.rect.x, pSettings->dest.rect.y, pSettings->dest.rect.width, pSettings->dest.rect.height,
1055        pSettings->colorOp, pSettings->alphaOp ));
1056
1057    rc = BGRClib_Blit(gfx->grclib, &gfx->blitData.blitParams, pColorKeyParams, pMatrixParams, pPatternParams, pScalingControlParams);
1058    BTRC_TRACE(nexus_graphics2d_blit, STOP);
1059    return NEXUS_Graphics2D_P_FinishOperation(gfx, rc);
1060}
1061
1062NEXUS_Error NEXUS_Graphics2D_FastBlit( NEXUS_Graphics2DHandle gfx,
1063    NEXUS_SurfaceHandle outputSurface, const NEXUS_Rect *pOutputRect, NEXUS_SurfaceHandle sourceSurface, const NEXUS_Rect *pSourceRect, NEXUS_BlitColorOp a_colorOp,
1064    NEXUS_BlitAlphaOp a_alphaOp, uint32_t constantColor )
1065{
1066    BERR_Code rc;
1067    BM2MC_PACKET_Plane src, out;
1068    unsigned srcPaletteOffset, temp;
1069    BGRCLib_BlitColorOp colorOp;
1070    BGRCLib_BlitAlphaOp alphaOp;
1071
1072    BTRC_TRACE(nexus_graphics2d_blit, START);
1073    BDBG_OBJECT_ASSERT(gfx, NEXUS_Graphics2D);
1074
1075    /* copy surfaces */
1076    NEXUS_Module_Lock( g_NEXUS_graphics2DData.settings.surface );
1077    NEXUS_Surface_InitPlane_priv(sourceSurface, &src, &srcPaletteOffset);
1078    NEXUS_Surface_InitPlane_priv(outputSurface, &out, &temp);
1079    NEXUS_Module_Unlock( g_NEXUS_graphics2DData.settings.surface );
1080
1081    /* Only CopySource is supported now. In the future, we could add NEXUS_BlitColorOp_eCopyConstant. This would be different from NEXUS_Graphics2D_Fill
1082    because you could fill color while copying alpha. */
1083    switch (a_colorOp) {
1084    case NEXUS_BlitColorOp_eCopySource:
1085        colorOp = BGRCLib_BlitColorOp_eCopySource;
1086        break;
1087    default:
1088        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
1089    }
1090
1091    switch (a_alphaOp) {
1092    case NEXUS_BlitAlphaOp_eCopySource:
1093        alphaOp = BGRCLib_BlitAlphaOp_eCopySource;
1094        {
1095            /* loop up pixel format info, but only when needed */
1096            const NEXUS_PixelFormatInfo *pSourcePixelFormatInfo = NEXUS_PixelFormat_GetInfo(src.format);
1097            if (!pSourcePixelFormatInfo->alpha_per_pixel) {
1098                alphaOp = BGRCLib_BlitAlphaOp_eUseConstAlpha;
1099                constantColor = 0xFF000000;
1100            }
1101        }
1102        break;
1103    case NEXUS_BlitAlphaOp_eCopyConstant:
1104        alphaOp = BGRCLib_BlitAlphaOp_eUseConstAlpha;
1105        break;
1106    default:
1107        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
1108    }
1109
1110    if (srcPaletteOffset) {
1111        BGRClib_GetDefaultPaletteBlitParams(&gfx->blitData.blitParams);
1112    } else {
1113        BGRClib_GetDefaultBlitParams(&gfx->blitData.blitParams);
1114    }
1115    gfx->blitData.blitParams.srcSurface = &src;
1116    gfx->blitData.blitParams.srcRect = (const BRect *)(void*)pSourceRect;
1117    gfx->blitData.blitParams.srcPaletteOffset = srcPaletteOffset;
1118    gfx->blitData.blitParams.outSurface = &out;
1119    gfx->blitData.blitParams.outRect = (const BRect *)(void*)pOutputRect;
1120    gfx->blitData.blitParams.colorOp = colorOp;
1121    gfx->blitData.blitParams.alphaOp = alphaOp;
1122    gfx->blitData.blitParams.constantColor = constantColor;
1123    gfx->blitData.blitParams.colorKeySelect = BGRC_Output_ColorKeySelection_eTakeBlend;
1124
1125    NEXUS_Graphics2D_P_SetPower(gfx, NEXUS_Graphics2DPowerState_ePowerUp);
1126
1127    BDBG_PRINT_OP(("fastblit source=%#x(%u,%u,%u,%u) output=%#x(%u,%u,%u,%u) op=%u,%u,%#x",
1128        (unsigned)outputSurface, 
1129        pSourceRect?pSourceRect->x:0, pSourceRect?pSourceRect->y:0, pSourceRect?pSourceRect->width:0, pSourceRect?pSourceRect->height:0,
1130        (unsigned)sourceSurface, 
1131        pOutputRect?pOutputRect->x:0, pOutputRect?pOutputRect->y:0, pOutputRect?pOutputRect->width:0, pOutputRect?pOutputRect->height:0,
1132        a_colorOp, a_alphaOp, constantColor
1133        ));
1134
1135    rc = BGRClib_Blit(gfx->grclib, &gfx->blitData.blitParams, NULL, NULL, NULL, NULL);
1136    BTRC_TRACE(nexus_graphics2d_blit, STOP);
1137
1138    return NEXUS_Graphics2D_P_FinishOperation(gfx, rc);
1139}
1140
1141void NEXUS_Graphics2D_GetDefaultPorterDuffBlitSettings(NEXUS_Graphics2DPorterDuffBlitSettings *pSettings )
1142{
1143    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
1144}
1145
1146NEXUS_Error NEXUS_Graphics2D_PorterDuffBlit(NEXUS_Graphics2DHandle gfx, const NEXUS_Graphics2DPorterDuffBlitSettings *pSettings)
1147{
1148    BM2MC_PACKET_Plane src, dst, out;
1149    BERR_Code rc;
1150    unsigned srcPaletteOffset, temp;
1151
1152    BTRC_TRACE(nexus_graphics2d_blit, START);
1153    BDBG_OBJECT_ASSERT(gfx, NEXUS_Graphics2D);
1154
1155    NEXUS_Module_Lock( g_NEXUS_graphics2DData.settings.surface );
1156    NEXUS_Surface_InitPlane_priv(pSettings->sourceSurface, &src, &srcPaletteOffset);
1157    if (pSettings->destSurface) {
1158        unsigned temp;
1159        NEXUS_Surface_InitPlane_priv(pSettings->destSurface, &dst, &temp);
1160    }
1161    NEXUS_Surface_InitPlane_priv(pSettings->outSurface, &out, &temp);
1162    NEXUS_Module_Unlock( g_NEXUS_graphics2DData.settings.surface );
1163
1164    BDBG_CASSERT(BGRCLib_PorterDuffOp_Count == (BGRCLib_PorterDuffOp)NEXUS_PorterDuffOp_eMax);
1165
1166    NEXUS_Graphics2D_P_SetPower(gfx, NEXUS_Graphics2DPowerState_ePowerUp);
1167
1168    BDBG_PRINT_OP(("porterDuff source=%#x(%u,%u,%u,%u) output=%#x(%u,%u,%u,%u) dest=%#x(%u,%u,%u,%u) op=%u",
1169        (unsigned)pSettings->sourceSurface, 
1170        pSettings->sourceRect.x, pSettings->sourceRect.y, pSettings->sourceRect.width, pSettings->sourceRect.height,
1171        (unsigned)pSettings->outSurface, 
1172        pSettings->outRect.x, pSettings->outRect.y, pSettings->outRect.width, pSettings->outRect.height,
1173        (unsigned)pSettings->destSurface, 
1174        pSettings->destRect.x, pSettings->destRect.y, pSettings->destRect.width, pSettings->destRect.height,
1175        pSettings->operation ));
1176
1177    rc = BGRClib_PorterDuffBlit(gfx->grclib, (BGRCLib_PorterDuffOp)pSettings->operation,
1178        &src, (const BRect *)(void*)&pSettings->sourceRect, srcPaletteOffset,
1179        pSettings->destSurface?&dst:NULL, (const BRect *)(void*)&pSettings->destRect,
1180        &out, (const BRect *)(void*)&pSettings->outRect);
1181    BTRC_TRACE(nexus_graphics2d_blit, STOP);
1182    return NEXUS_Graphics2D_P_FinishOperation(gfx, rc);
1183}
1184
1185void NEXUS_Graphics2D_P_SetPower(NEXUS_Graphics2DHandle gfx, NEXUS_Graphics2DPowerState powerState)
1186{
1187    struct NEXUS_Graphics2DEngine *engine;
1188    BDBG_OBJECT_ASSERT(gfx, NEXUS_Graphics2D);
1189    engine = &g_grcInstance[gfx->index];
1190
1191    /* Graphics2DEngine has its own powerOn boolean to ensure the NEXUS_PowerManagement refcnt doesn't get off */
1192    if (powerState == NEXUS_Graphics2DPowerState_ePowerUp) {
1193        if (!engine->powerOn) {
1194            NEXUS_PowerManagement_SetCoreState(NEXUS_PowerManagementCore_eGraphics2D, true);
1195            engine->powerOn = true;
1196        }
1197    }
1198    else {
1199        if (engine->powerOn) {
1200            NEXUS_PowerManagement_SetCoreState(NEXUS_PowerManagementCore_eGraphics2D, false);
1201            engine->powerOn = false;
1202        }
1203    }
1204}
1205
1206static BERR_Code NEXUS_Graphics2D_PacketCallback_isr( BGRC_Handle grc, void *data )
1207{
1208    struct NEXUS_Graphics2DEngine *engine = data;
1209    BSTD_UNUSED(grc);
1210    BDBG_PRINT_OP(("NEXUS_Graphics2D_PacketCallback_isr"));
1211    BKNI_SetEvent(engine->advanceEvent);
1212    return NEXUS_SUCCESS;
1213}
1214
1215static void NEXUS_Graphics2D_P_PacketAdvance( void *context )
1216{
1217    BERR_Code rc;
1218    struct NEXUS_Graphics2DEngine *engine = context;
1219    size_t n;
1220    unsigned i;
1221    BGRC_Packet_ContextStatus *array = engine->contextStatus;
1222
1223    /* advance all */
1224    rc = BGRC_Packet_AdvancePackets(engine->grc, NULL);
1225    if (rc && rc != BGRC_PACKET_MSG_PACKETS_INCOMPLETE) {
1226        rc = BERR_TRACE(rc);
1227        return;
1228    }
1229
1230    rc = BGRC_Packet_GetContextStatus(engine->grc, array, &n, NEXUS_GRAPHICS2D_MAX_CONTEXTS);
1231    if (rc) {rc = BERR_TRACE(rc); return;}
1232
1233    BDBG_PRINT_OP(("NEXUS_Graphics2D_P_PacketAdvance %d contexts", n));
1234    for (i=0;i<n;i++) {
1235        NEXUS_Graphics2DHandle gfx;
1236
1237        gfx = array[i].private_data;
1238        BDBG_OBJECT_ASSERT(gfx, NEXUS_Graphics2D);
1239        BDBG_PRINT_OP(("  %d: avail=%d, sync=%d, checkpointCount=%d", i, array[i].packet_buffer_available, array[i].sync, gfx->checkpointCount));
1240
1241        if (gfx->packetSpaceAvailableCount && array[i].packet_buffer_available) {
1242            if (--gfx->packetSpaceAvailableCount == 0) {
1243                NEXUS_TaskCallback_Fire(gfx->packetSpaceAvailable);
1244            }
1245        }
1246        if (gfx->checkpointCount && array[i].sync) {
1247            if (--gfx->checkpointCount == 0 && !gfx->settings.pollingCheckpoint) {
1248                NEXUS_TaskCallback_Fire(gfx->checkpoint);
1249            }
1250        }
1251    }
1252
1253}
1254
1255
1256NEXUS_Error NEXUS_Graphics2D_Checkpoint( NEXUS_Graphics2DHandle gfx, const NEXUS_CallbackDesc *pCallback )
1257{
1258    NEXUS_Error rc, rc2;
1259
1260    BDBG_OBJECT_ASSERT(gfx, NEXUS_Graphics2D);
1261   
1262    gfx->checkpointWatchdog.counter = 0;
1263
1264    if (gfx->settings.pollingCheckpoint) {
1265        /* pollingCheckpoint still requires an internal sync if no checkpoint is pending.
1266        the one difference is that we avoid scheduling extra checkpoints and we prevent any callback to the app. */
1267        if (gfx->checkpointCount) {
1268            return NEXUS_GRAPHICS2D_BUSY;
1269        }
1270    }
1271    else {
1272        if ( pCallback && gfx->settings.checkpointCallback.callback ) {
1273            return BERR_TRACE(NEXUS_NOT_SUPPORTED);
1274        }
1275        if (gfx->checkpointCount) {
1276            /* after calling checkpoint, you must wait for the checkpoint callback before calling checkpoint again.
1277            this is a failure because we cannot reset the checkpoint. the app must wait. if it does not, graphics tearing will likely result. */
1278            return BERR_TRACE(NEXUS_NOT_AVAILABLE);
1279        }
1280       
1281        /* it's now allowed to call checkpoint with no callback. it can be used to "submit" blits
1282        regardless of the threshold */
1283        if (pCallback) {
1284            NEXUS_TaskCallback_Set( gfx->checkpoint, pCallback );
1285        }
1286    }
1287
1288    NEXUS_Graphics2D_P_SetPower(gfx, NEXUS_Graphics2DPowerState_ePowerUp);
1289
1290    rc = BGRC_Packet_SyncPackets(gfx->grc, gfx->packetContext);
1291    switch (rc) {
1292    case 0:
1293    case BGRC_PACKET_MSG_PACKETS_INCOMPLETE:
1294        rc = 0;
1295        break;
1296    case BGRC_PACKET_MSG_BLITS_COMPLETE:
1297        break;
1298    default: 
1299        return BERR_TRACE(rc);
1300    }
1301       
1302    rc2 = BGRC_Packet_SyncPackets(gfx->grc, gfx->functionContext);
1303    switch (rc2) {
1304    case 0:
1305    case BGRC_PACKET_MSG_PACKETS_INCOMPLETE:
1306        rc2 = 0;
1307        break;
1308    case BGRC_PACKET_MSG_BLITS_COMPLETE:
1309        break;
1310    default: 
1311        return BERR_TRACE(rc2);
1312    }
1313       
1314    if (rc == BGRC_PACKET_MSG_BLITS_COMPLETE && rc2 == BGRC_PACKET_MSG_BLITS_COMPLETE) {
1315        /* no blits queue in either context. */
1316        return 0; /* no blits queued */
1317    }
1318    else if (!rc || !rc2) {
1319        /* blits are queued in at least one context */
1320        BDBG_ASSERT(!gfx->checkpointCount);
1321        if (!rc) gfx->checkpointCount++;
1322        if (!rc2) gfx->checkpointCount++;
1323        if (gfx->settings.pollingCheckpoint) {
1324            return NEXUS_GRAPHICS2D_BUSY;
1325        }
1326        else {
1327            return NEXUS_GRAPHICS2D_QUEUED;
1328        }
1329    }
1330    else {
1331        return BERR_TRACE(rc);
1332    }
1333}
1334
1335void NEXUS_Graphics2D_GetDefaultBatchBlitSettings(NEXUS_Graphics2DBatchBlitSettings *pSettings)
1336{
1337    BKNI_Memset(pSettings, 0, sizeof(*pSettings));
1338}
1339
1340NEXUS_Error NEXUS_Graphics2D_BatchBlit( NEXUS_Graphics2DHandle gfx,
1341    size_t count, size_t index, size_t *next,
1342    const NEXUS_Graphics2DBatchBlitSettings *pBatchSettings,
1343    const NEXUS_Graphics2DBlitSettings *pBlitSettings )
1344{
1345    BDBG_OBJECT_ASSERT(gfx, NEXUS_Graphics2D);
1346    BSTD_UNUSED(count);
1347    BSTD_UNUSED(index);
1348    BSTD_UNUSED(next);
1349    BSTD_UNUSED(pBatchSettings);
1350    BSTD_UNUSED(pBlitSettings);
1351    return BERR_TRACE(NEXUS_NOT_SUPPORTED);
1352}
1353
1354NEXUS_Error NEXUS_Graphics2D_Memset32( NEXUS_Graphics2DHandle gfx, void *address, uint32_t data, unsigned count )
1355{
1356    NEXUS_Error err = NEXUS_SUCCESS;
1357    uint32_t offset;
1358
1359    if (count < 0x400 || count > 0x1000000) { /* 1K to 16M */
1360        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
1361    }
1362    if (count % 0x400) { /* must be multiple of 1K */
1363        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
1364    }
1365
1366    offset = NEXUS_AddrToOffset(address);
1367    if( offset == 0 )
1368    {
1369        BDBG_ERR(("Invalid memory address %p specified", address));
1370        return BERR_TRACE(NEXUS_INVALID_PARAMETER);
1371    }
1372
1373    NEXUS_Graphics2D_P_SetPower(gfx, NEXUS_Graphics2DPowerState_ePowerUp);
1374
1375    err = BGRClib_Memset32( gfx->grclib, offset, data, count);
1376
1377    return BERR_TRACE(err);
1378}
1379
1380NEXUS_Error NEXUS_Graphics2D_GetPacketBuffer( NEXUS_Graphics2DHandle gfx, void **buffer, size_t *pSize, size_t minSize )
1381{
1382    BERR_Code rc;
1383    BDBG_OBJECT_ASSERT(gfx, NEXUS_Graphics2D);
1384   
1385    if (!gfx->verifyPacketHeap) {
1386        /* packet buffer memory must be CPU accessible for application and driver. we can only check driver mapping here.
1387        only verify once for optimal performance. */
1388        if (gfx->openSettings.heap && !NEXUS_P_CpuAccessibleHeap(gfx->openSettings.heap)) {
1389            return BERR_TRACE(NEXUS_NOT_AVAILABLE);
1390        }
1391        gfx->verifyPacketHeap = true;
1392    }
1393   
1394    NEXUS_Graphics2D_P_SetPower(gfx, NEXUS_Graphics2DPowerState_ePowerUp);
1395    rc = BGRC_Packet_GetPacketMemory(gfx->grc, gfx->packetContext, buffer, pSize, minSize);
1396    if (rc || *pSize < minSize) {
1397        *buffer = NULL;
1398        *pSize = 0;
1399        gfx->packetSpaceAvailableCount++;
1400    }
1401    return 0;
1402}
1403
1404NEXUS_Error NEXUS_Graphics2D_PacketWriteComplete( NEXUS_Graphics2DHandle gfx, size_t size )
1405{
1406    BERR_Code rc;
1407    BDBG_OBJECT_ASSERT(gfx, NEXUS_Graphics2D);
1408    NEXUS_Graphics2D_P_SetPower(gfx, NEXUS_Graphics2DPowerState_ePowerUp);
1409    rc = BGRC_Packet_SubmitPackets(gfx->grc, gfx->packetContext, size);
1410    return !rc || (rc == BGRC_PACKET_MSG_PACKETS_INCOMPLETE) ? BERR_SUCCESS : BERR_TRACE(rc);
1411}
1412
1413NEXUS_Error NEXUS_Graphics2D_ConvertFilter( NEXUS_Graphics2DFilterCoeffs filter, size_t srcSize, size_t outSize, BM2MC_PACKET_FilterCoeffs *pCoeffs )
1414{
1415    return BGRC_Packet_ConvertFilter(pCoeffs, filter, srcSize, outSize);
1416}
1417
1418NEXUS_Error NEXUS_Graphics2D_ConvertColorMatrix( const NEXUS_Graphics2DColorMatrix *pMatrixIn, BM2MC_PACKET_ColorMatrix *pMatrixOut )
1419{
1420    return BGRC_Packet_ConvertColorMatrix(pMatrixOut, pMatrixIn->coeffMatrix, pMatrixIn->shift);
1421}
1422
1423NEXUS_Error NEXUS_Graphics2DModule_Standby_priv(bool enabled, const NEXUS_StandbySettings *pSettings)
1424{
1425#if NEXUS_POWER_MANAGEMENT
1426    int i;
1427    NEXUS_Error rc;
1428
1429    BSTD_UNUSED(pSettings);
1430   
1431    if (!enabled) { 
1432        /* For power up we only need to turn on SRAM power. We power up M2MC when we setup an operation */   
1433        NEXUS_PowerManagement_SetCoreState(NEXUS_PowerManagementCore_eGraphics2DMemory, true);
1434
1435        /* re-enable the GRC callback */
1436        for (i=0; i<NEXUS_NUM_2D_ENGINES; i++) {
1437            struct NEXUS_Graphics2DEngine *engine = &g_grcInstance[i];
1438            NEXUS_Graphics2DHandle gfx = BLST_S_FIRST(&engine->contexts);
1439            if (!gfx) {continue;}
1440           
1441            NEXUS_Graphics2D_P_SetPower(gfx, NEXUS_Graphics2DPowerState_ePowerUp);
1442            rc = BGRC_Packet_SetCallback(gfx->grc, NEXUS_Graphics2D_PacketCallback_isr, engine);
1443            if (rc) {rc = BERR_TRACE(rc); return 0; }
1444            NEXUS_Graphics2D_P_SetPower(gfx, NEXUS_Graphics2DPowerState_ePowerDown);
1445        }
1446    } else {
1447        /* For power down we just need to check for pending operations and return the error code */
1448        for (i=0; i<NEXUS_NUM_2D_ENGINES; i++) {
1449            struct NEXUS_Graphics2DEngine *engine = &g_grcInstance[i];
1450            NEXUS_Graphics2DHandle gfx = BLST_S_FIRST(&engine->contexts);
1451            BGRC_Packet_Status grcStatus;
1452       
1453            if (!gfx) {continue;}
1454       
1455            NEXUS_Graphics2D_P_SetPower(gfx, NEXUS_Graphics2DPowerState_ePowerUp);
1456
1457            rc = BGRC_Packet_GetStatus(gfx->grc, &grcStatus);
1458            if (rc) {rc = BERR_TRACE(rc); return 0;}
1459            if (!grcStatus.m2mc_busy) {
1460                /* disable the GRC callback */
1461                rc = BGRC_Packet_SetCallback(gfx->grc, NULL, NULL);
1462                if (rc) {rc = BERR_TRACE(rc); return 0; }
1463               
1464                /* m2mc_busy==0 means that no blits are active and no blits are queued.
1465                   therefore we can power down M2MC safely */
1466                NEXUS_Graphics2D_P_SetPower(gfx, NEXUS_Graphics2DPowerState_ePowerDown);
1467            } else {
1468                return NEXUS_GRAPHICS2D_QUEUED;
1469            }
1470        }
1471        NEXUS_PowerManagement_SetCoreState(NEXUS_PowerManagementCore_eGraphics2DMemory, false);
1472    }
1473#else
1474    BSTD_UNUSED(enabled);
1475    BSTD_UNUSED(pSettings);
1476#endif
1477    return NEXUS_SUCCESS;
1478}
1479
1480static void nexus_graphics2d_p_checkpoint_watchdog(void *context)
1481{
1482    NEXUS_Graphics2DHandle gfx = context;
1483    if (gfx->checkpointWatchdog.counter) {
1484        if (--gfx->checkpointWatchdog.counter == 0) {
1485            /* if packetFifoThreshold is non-zero, blits will be queued until the fifo is full
1486            or NEXUS_Graphics2D_Checkpoint is issued. an app should not rely on filling the fifo, so a checkpoint
1487            is required. */
1488            BDBG_ERR(("missing call to NEXUS_Graphics2D_Checkpoint. blit is queued.", gfx));
1489        }
1490    }
1491    gfx->checkpointWatchdog.timer = NEXUS_ScheduleTimer(5*1000 /* 5 seconds */, nexus_graphics2d_p_checkpoint_watchdog, gfx);
1492    if (!gfx->checkpointWatchdog.timer) { BERR_TRACE(NEXUS_OUT_OF_SYSTEM_MEMORY); }
1493}
Note: See TracBrowser for help on using the repository browser.