1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - dsp
3 File: dsp_graphics.c
4
5 Copyright 2008-2009 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2009-06-19#$
14 $Rev: 10786 $
15 $Author: okajima_manabu $
16 *---------------------------------------------------------------------------*/
17 #include <twl.h>
18 #include <twl/dsp.h>
19 #include <twl/dsp/common/graphics.h>
20
21 #include "dsp_process.h"
22
23 extern const u8 DSPiFirmware_graphics[];
24
25 /*---------------------------------------------------------------------------*/
26 /* Variables */
27
28 static DSPPipe binOut[1];
29 static BOOL DSPiGraphicsAvailable = FALSE;
30 static DSPProcessContext DSPiProcessGraphics[1];
31
32 static u16 replyReg;
33
34 /* Determine whether limitation conditions have been met (FALSE if so) */
35 static BOOL CheckLimitation(f32 rx, f32 ry, DSPGraphicsScalingMode mode, u16 src_width);
36
37 /*---------------------------------------------------------------------------*/
38 /* Functions */
39 /*---------------------------------------------------------------------------*
40 Name: CheckLimitation
41
42 Description: Determines if limitation conditions set by the DSP_Scaling* functions' specifications have been met.
43
44 Arguments: mode: Scaling mode
45 rx, ry: Horizontal and vertical scaling factors
46 src_width: Width of the input image
47
48 Returns: FALSE if limitation conditions have been met
49 *---------------------------------------------------------------------------*/
CheckLimitation(f32 rx,f32 ry,DSPGraphicsScalingMode mode,u16 src_width)50 static BOOL CheckLimitation(f32 rx, f32 ry, DSPGraphicsScalingMode mode, u16 src_width)
51 {
52 // When the processed data size is at least as large as the original data size
53 if (rx * ry >= 1.0f)
54 {
55 switch(mode)
56 {
57 case DSP_GRAPHICS_SCALING_MODE_N_NEIGHBOR:
58 case DSP_GRAPHICS_SCALING_MODE_BILINEAR:
59 if (DSP_CALC_SCALING_SIZE(src_width, rx) * ry >= 8192)
60 {
61 return FALSE;
62 }
63 break;
64 case DSP_GRAPHICS_SCALING_MODE_BICUBIC:
65 if (DSP_CALC_SCALING_SIZE(src_width, rx) * ry >= 4096)
66 {
67 return FALSE;
68 }
69 break;
70 }
71 }
72 else // When the processed data size is less than the original data size
73 {
74 switch(mode)
75 {
76 case DSP_GRAPHICS_SCALING_MODE_N_NEIGHBOR:
77 case DSP_GRAPHICS_SCALING_MODE_BILINEAR:
78 if (src_width >= 8192)
79 {
80 return FALSE;
81 }
82 break;
83 case DSP_GRAPHICS_SCALING_MODE_BICUBIC:
84 if (src_width >= 4096)
85 {
86 return FALSE;
87 }
88 break;
89 }
90 }
91 return TRUE;
92 }
93
94 /*---------------------------------------------------------------------------*
95 Name: DSPi_OpenStaticComponentGraphicsCore
96
97 Description: Opens the memory file(s) for the graphics component.
98 It is no longer necessary to prepare a file system in advance, but because it is linked as static memory, the program size increases.
99
100
101 Arguments: file: FSFile structure that opens the memory file
102
103 Returns: None.
104 *---------------------------------------------------------------------------*/
DSPi_OpenStaticComponentGraphicsCore(FSFile * file)105 void DSPi_OpenStaticComponentGraphicsCore(FSFile *file)
106 {
107 extern const u8 DSPiFirmware_graphics[];
108 (void)DSPi_CreateMemoryFile(file, DSPiFirmware_graphics);
109 }
110
111 /*---------------------------------------------------------------------------*
112 Name: DSPi_GraphicsEvents(void *userdata)
113
114 Description: Event handler of the DSP graphics component.
115
116 Arguments: None.
117
118 Returns: None.
119 *---------------------------------------------------------------------------*/
DSPi_GraphicsEvents(void * userdata)120 static void DSPi_GraphicsEvents(void *userdata)
121 {
122 (void)userdata;
123
124 // When running asynchronous processing, check for the presence of completion notices
125 if ( isAsync )
126 {
127 replyReg = DSP_RecvData(DSP_GRAPHICS_REP_REGISTER);
128 if (replyReg == DSP_STATE_SUCCESS)
129 {
130 isBusy = FALSE;
131 isAsync = FALSE;
132
133 if ( callBackFunc != NULL)
134 {
135 callBackFunc();
136 }
137 }
138 else if (replyReg == DSP_STATE_FAIL)
139 {
140 OS_TWarning("a process on DSP is failed.\n");
141 isBusy = FALSE;
142 isAsync = FALSE;
143 }
144 else
145 {
146 OS_TWarning("unknown error occured.\n");
147 isBusy = FALSE;
148 isAsync = FALSE;
149 }
150 }
151 else // Synchronous version
152 {
153 // replyReg = DSP_RecvData(DSP_GRAPHICS_REP_REGISTER);
154 // isBusy = FALSE;
155 }
156 }
157
158 /*---------------------------------------------------------------------------*
159 Name: DSP_LoadGraphicsCore
160
161 Description: Loads graphics component to DSP.
162
163 Arguments: file: Graphics component file
164 slotB: WRAM-B allowed for use for code memory
165 slotC: WRAM-C allowed for use for data memory
166
167 Returns: TRUE if the graphics component is correctly loaded to DSP.
168 *---------------------------------------------------------------------------*/
DSPi_LoadGraphicsCore(FSFile * file,int slotB,int slotC)169 BOOL DSPi_LoadGraphicsCore(FSFile *file, int slotB, int slotC)
170 {
171 if (!DSPiGraphicsAvailable)
172 {
173 isBusy = FALSE;
174 isAsync = FALSE;
175 DSP_InitProcessContext(DSPiProcessGraphics, "graphics");
176 // (If there is specification to a linker script file on the DSP side, this explicit setting is unnecessary)
177 DSPiProcessGraphics->flags |= DSP_PROCESS_FLAG_USING_OS;
178 DSP_SetProcessHook(DSPiProcessGraphics,
179 DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
180 DSPi_GraphicsEvents, NULL);
181 if (DSP_ExecuteProcess(DSPiProcessGraphics, file, slotB, slotC))
182 {
183 DSPiGraphicsAvailable = TRUE;
184 }
185
186 (void)DSP_LoadPipe(binOut, DSP_PIPE_BINARY, DSP_PIPE_OUTPUT);
187 }
188
189 return DSPiGraphicsAvailable;
190 }
191
192 /*---------------------------------------------------------------------------*
193 Name: DSP_UnloadGraphicsCore
194
195 Description: Ends the DSP graphics component.
196
197 Arguments: None.
198
199 Returns: None.
200 *---------------------------------------------------------------------------*/
DSPi_UnloadGraphicsCore(void)201 void DSPi_UnloadGraphicsCore(void)
202 {
203 if(DSPiGraphicsAvailable)
204 {
205 DSP_QuitProcess(DSPiProcessGraphics);
206 DSPiGraphicsAvailable = FALSE;
207 }
208 }
209
210 /*---------------------------------------------------------------------------*
211 Name: DSPi_YuvToRgbConvertCore
212
213 Description: Converts YUV to RGB.
214
215 Arguments: src: Address of (source) data to process
216 dest: Address for storing data (destination) after processing
217 size: Size of src data
218 callback: Pointer for callback function run after conversion ends
219 async: TRUE when running asynchronously
220
221 Returns: TRUE if successful.
222 *---------------------------------------------------------------------------*/
DSPi_ConvertYuvToRgbCore(const void * src,void * dst,u32 size,DSP_GraphicsCallback callback,BOOL async)223 BOOL DSPi_ConvertYuvToRgbCore(const void* src, void* dst, u32 size, DSP_GraphicsCallback callback, BOOL async)
224 {
225 DSPYuv2RgbParam yr_param;
226 u32 offset = 0;
227 u16 command;
228
229 // Check one more time whether DSP is busy
230 if (isBusy)
231 {
232 OS_TPrintf("dsp is busy.\n");
233 return FALSE;
234 }
235 isBusy = TRUE;
236
237 // Register the callback function
238 callBackFunc = callback;
239 isAsync = async;
240
241 if (async)
242 {
243 DSP_SetProcessHook(DSPiProcessGraphics,
244 DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
245 DSPi_GraphicsEvents, NULL);
246 }
247 else
248 {
249 DSP_SetProcessHook(DSPiProcessGraphics,
250 DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
251 NULL, NULL);
252 }
253
254 // Notify the DSP of the content of processes to start
255 command = DSP_G_FUNCID_YUV2RGB;
256 DSP_SendData(DSP_GRAPHICS_COM_REGISTER, command);
257
258 // Send parameters to DSP
259 yr_param.size = size;
260 yr_param.src = (u32)((u32)src + offset);
261 yr_param.dst = (u32)((u32)dst + offset);
262
263 DSP_WritePipe(binOut, &yr_param, sizeof(DSPYuv2RgbParam));
264
265 if (async)
266 {
267 return TRUE;
268 }
269 else
270 {
271 // Wait for a reply from the DSP
272 while (!DSP_RecvDataIsReady(DSP_GRAPHICS_REP_REGISTER)) {
273 OS_Sleep(1);
274 }
275 replyReg = DSP_RecvData(DSP_GRAPHICS_REP_REGISTER);
276 isBusy = FALSE;
277
278 if ( replyReg == DSP_STATE_SUCCESS)
279 {
280 return TRUE;
281 }
282 else
283 {
284 return FALSE;
285 }
286 }
287
288 return FALSE;
289 }
290
291 /*---------------------------------------------------------------------------*
292 Name: DSPi_ScalingCore
293
294 Description: Scales the image data.
295
296 Returns: TRUE if successful.
297 *---------------------------------------------------------------------------*/
DSPi_ScalingCore(const void * src,void * dst,u16 img_width,u16 img_height,f32 rx,f32 ry,DSPGraphicsScalingMode mode,u16 x,u16 y,u16 width,u16 height,DSP_GraphicsCallback callback,BOOL async)298 BOOL DSPi_ScalingCore(const void* src, void* dst, u16 img_width, u16 img_height, f32 rx, f32 ry, DSPGraphicsScalingMode mode,
299 u16 x, u16 y, u16 width, u16 height, DSP_GraphicsCallback callback, BOOL async)
300 {
301 DSPScalingParam sc_param;
302
303 u16 command;
304
305 // Check limitation conditions
306 SDK_TASSERTMSG(CheckLimitation(rx, ry, mode, width), "DSP_Scaling: arguments exceed the limit.");
307
308 // Check one more time whether DSP is busy
309 if (isBusy)
310 {
311 OS_TPrintf("dsp is busy.\n");
312 return FALSE;
313 }
314 isBusy = TRUE;
315
316 // Register the callback function
317 callBackFunc = callback;
318 isAsync = async;
319 if (async)
320 {
321 DSP_SetProcessHook(DSPiProcessGraphics,
322 DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
323 DSPi_GraphicsEvents, NULL);
324 }
325 else
326 {
327 DSP_SetProcessHook(DSPiProcessGraphics,
328 DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
329 NULL, NULL);
330 }
331
332 // Notify the DSP of the content of processes to start
333 command = DSP_G_FUNCID_SCALING;
334 DSP_SendData(DSP_GRAPHICS_COM_REGISTER, command);
335
336 // Transfer parameters to DSP
337 sc_param.src = (u32)src;
338 sc_param.dst = (u32)dst;
339 sc_param.mode = mode;
340 sc_param.img_width = img_width;
341 sc_param.img_height = img_height;
342 sc_param.rate_w = (u16)(rx * 1000);
343 sc_param.rate_h = (u16)(ry * 1000);
344 sc_param.block_x = x;
345 sc_param.block_y = y;
346 sc_param.width = width;
347 sc_param.height = height;
348
349 DSP_WritePipe(binOut, &sc_param, sizeof(DSPScalingParam));
350
351 // Branch if processing asynchronously
352 if(isAsync)
353 {
354 return TRUE;
355 }
356 else
357 {
358 // Wait for a reply from the DSP
359 while (!DSP_RecvDataIsReady(DSP_GRAPHICS_REP_REGISTER)) {
360 OS_Sleep(1);
361 }
362
363 replyReg = DSP_RecvData(DSP_GRAPHICS_REP_REGISTER);
364 isBusy = FALSE;
365
366 if ( replyReg == DSP_STATE_SUCCESS )
367 {
368 return TRUE;
369 }
370 else
371 {
372 return FALSE;
373 }
374 }
375
376 return FALSE;
377 }
378
DSPi_ScalingFxCore(const void * src,void * dst,u16 img_width,u16 img_height,fx32 rx,fx32 ry,DSPGraphicsScalingMode mode,u16 x,u16 y,u16 width,u16 height,DSP_GraphicsCallback callback,BOOL async)379 BOOL DSPi_ScalingFxCore(const void* src, void* dst, u16 img_width, u16 img_height, fx32 rx, fx32 ry, DSPGraphicsScalingMode mode,
380 u16 x, u16 y, u16 width, u16 height, DSP_GraphicsCallback callback, BOOL async)
381 {
382 DSPScalingParam sc_param;
383
384 u16 command;
385
386 // Check limitation conditions
387 SDK_TASSERTMSG(CheckLimitation(FX_FX32_TO_F32(rx), FX_FX32_TO_F32(ry), mode, width), "DSP_Scaling: arguments exceed the limit.");
388
389 // Check one more time whether DSP is busy
390 if (isBusy)
391 {
392 OS_TPrintf("dsp is busy.\n");
393 return FALSE;
394 }
395 isBusy = TRUE;
396
397 // Register the callback function
398 callBackFunc = callback;
399 isAsync = async;
400
401 if (async)
402 {
403 DSP_SetProcessHook(DSPiProcessGraphics,
404 DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
405 DSPi_GraphicsEvents, NULL);
406 }
407 else
408 {
409 DSP_SetProcessHook(DSPiProcessGraphics,
410 DSP_HOOK_REPLY_(DSP_GRAPHICS_REP_REGISTER),
411 NULL, NULL);
412 }
413
414 // Notify the DSP of the content of processes to start
415 command = DSP_G_FUNCID_SCALING;
416 DSP_SendData(DSP_GRAPHICS_COM_REGISTER, command);
417
418 // Transfer parameters to DSP
419 sc_param.src = (u32)src;
420 sc_param.dst = (u32)dst;
421 sc_param.mode = mode;
422 sc_param.img_width = img_width;
423 sc_param.img_height = img_height;
424 sc_param.rate_w = (u16)(rx / 4096.0f * 1000);
425 sc_param.rate_h = (u16)(ry / 4096.0f * 1000);
426 sc_param.block_x = x;
427 sc_param.block_y = y;
428 sc_param.width = width;
429 sc_param.height = height;
430
431 DSP_WritePipe(binOut, &sc_param, sizeof(DSPScalingParam));
432
433 // Branch if processing asynchronously
434 if(isAsync)
435 {
436 return TRUE;
437 }
438 else
439 {
440 // Wait for a reply from the DSP
441 while (!DSP_RecvDataIsReady(DSP_GRAPHICS_REP_REGISTER)) {
442 OS_Sleep(1);
443 }
444 replyReg = DSP_RecvData(DSP_GRAPHICS_REP_REGISTER);
445 isBusy = FALSE;
446
447 if ( replyReg == DSP_STATE_SUCCESS )
448 {
449 return TRUE;
450 }
451 else
452 {
453 return FALSE;
454 }
455 }
456
457 return FALSE;
458 }
459
460