e14743d1 |
1 | /* |
2 | * SDL - Simple DirectMedia Layer |
3 | * CELL BE Support for PS3 Framebuffer |
4 | * Copyright (C) 2008, 2009 International Business Machines Corporation |
5 | * |
6 | * This library is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU Lesser General Public License as published |
8 | * by the Free Software Foundation; either version 2.1 of the License, or |
9 | * (at your option) any later version. |
10 | * |
11 | * This library is distributed in the hope that it will be useful, but |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Lesser General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Lesser General Public |
17 | * License along with this library; if not, write to the Free Software |
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 |
19 | * USA |
20 | * |
21 | * Martin Lowinski <lowinski [at] de [dot] ibm [ibm] com> |
22 | * Dirk Herrendoerfer <d.herrendoerfer [at] de [dot] ibm [dot] com> |
23 | * SPE code based on research by: |
24 | * Rene Becker |
25 | * Thimo Emmerich |
26 | */ |
27 | |
28 | #include "spu_common.h" |
29 | |
30 | #include <spu_intrinsics.h> |
31 | #include <spu_mfcio.h> |
32 | #include <stdio.h> |
33 | #include <string.h> |
34 | |
35 | // Debugging |
36 | //#define DEBUG |
37 | |
38 | #ifdef DEBUG |
39 | #define deprintf(fmt, args... ) \ |
40 | fprintf( stdout, fmt, ##args ); \ |
41 | fflush( stdout ); |
42 | #else |
43 | #define deprintf( fmt, args... ) |
44 | #endif |
45 | |
46 | void cpy_to_fb(unsigned int); |
47 | |
48 | /* fb_writer_spu parms */ |
49 | static volatile struct fb_writer_parms_t parms __attribute__ ((aligned(128))); |
50 | |
51 | /* Code running on SPU */ |
52 | int main(unsigned long long spe_id __attribute__ ((unused)), unsigned long long argp __attribute__ ((unused))) |
53 | { |
54 | deprintf("[SPU] fb_writer_spu is up... (on SPE #%llu)\n", spe_id); |
55 | uint32_t ea_mfc, mbox; |
56 | // send ready message |
57 | spu_write_out_mbox(SPU_READY); |
58 | |
59 | while (1) { |
60 | /* Check mailbox */ |
61 | mbox = spu_read_in_mbox(); |
62 | deprintf("[SPU] Message is %u\n", mbox); |
63 | switch (mbox) { |
64 | case SPU_EXIT: |
65 | deprintf("[SPU] fb_writer goes down...\n"); |
66 | return 0; |
67 | case SPU_START: |
68 | break; |
69 | default: |
70 | deprintf("[SPU] Cannot handle message\n"); |
71 | continue; |
72 | } |
73 | |
74 | /* Tag Manager setup */ |
75 | unsigned int tags; |
76 | tags = mfc_multi_tag_reserve(5); |
77 | if (tags == MFC_TAG_INVALID) { |
78 | deprintf("[SPU] Failed to reserve mfc tags on fb_writer\n"); |
79 | return 0; |
80 | } |
81 | |
82 | /* Framebuffer parms */ |
83 | ea_mfc = spu_read_in_mbox(); |
84 | deprintf("[SPU] Message on fb_writer is %u\n", ea_mfc); |
85 | spu_mfcdma32(&parms, (unsigned int)ea_mfc, |
86 | sizeof(struct fb_writer_parms_t), tags, |
87 | MFC_GET_CMD); |
88 | deprintf("[SPU] argp = %u\n", (unsigned int)argp); |
89 | DMA_WAIT_TAG(tags); |
90 | |
91 | /* Copy parms->data to framebuffer */ |
92 | deprintf("[SPU] Copying to framebuffer started\n"); |
93 | cpy_to_fb(tags); |
94 | deprintf("[SPU] Copying to framebuffer done!\n"); |
95 | |
96 | mfc_multi_tag_release(tags, 5); |
97 | deprintf("[SPU] fb_writer_spu... done!\n"); |
98 | /* Send FIN msg */ |
99 | spu_write_out_mbox(SPU_FIN); |
100 | } |
101 | |
102 | return 0; |
103 | } |
104 | |
105 | void cpy_to_fb(unsigned int tag_id_base) |
106 | { |
107 | unsigned int i; |
108 | unsigned char current_buf; |
109 | uint8_t *in = parms.data; |
110 | |
111 | /* Align fb pointer which was centered before */ |
112 | uint8_t *fb = |
113 | (unsigned char *)((unsigned int)parms.center & 0xFFFFFFF0); |
114 | |
115 | uint32_t bounded_input_height = parms.bounded_input_height; |
116 | uint32_t bounded_input_width = parms.bounded_input_width; |
117 | uint32_t fb_pixel_size = parms.fb_pixel_size; |
118 | |
119 | uint32_t out_line_stride = parms.out_line_stride; |
120 | uint32_t in_line_stride = parms.in_line_stride; |
121 | uint32_t in_line_size = bounded_input_width * fb_pixel_size; |
122 | |
123 | current_buf = 0; |
124 | |
125 | /* Local store buffer */ |
126 | static volatile uint8_t buf[4][BUFFER_SIZE] |
127 | __attribute__ ((aligned(128))); |
128 | /* do 4-times multibuffering using DMA list, process in two steps */ |
129 | for (i = 0; i < bounded_input_height >> 2; i++) { |
130 | /* first buffer */ |
131 | DMA_WAIT_TAG(tag_id_base + 1); |
132 | // retrieve buffer |
133 | spu_mfcdma32(buf[0], (unsigned int)in, in_line_size, |
134 | tag_id_base + 1, MFC_GETB_CMD); |
135 | DMA_WAIT_TAG(tag_id_base + 1); |
136 | // store buffer |
137 | spu_mfcdma32(buf[0], (unsigned int)fb, in_line_size, |
138 | tag_id_base + 1, MFC_PUTB_CMD); |
139 | in += in_line_stride; |
140 | fb += out_line_stride; |
141 | deprintf("[SPU] 1st buffer copied in=0x%x, fb=0x%x\n", in, |
142 | fb); |
143 | |
144 | /* second buffer */ |
145 | DMA_WAIT_TAG(tag_id_base + 2); |
146 | // retrieve buffer |
147 | spu_mfcdma32(buf[1], (unsigned int)in, in_line_size, |
148 | tag_id_base + 2, MFC_GETB_CMD); |
149 | DMA_WAIT_TAG(tag_id_base + 2); |
150 | // store buffer |
151 | spu_mfcdma32(buf[1], (unsigned int)fb, in_line_size, |
152 | tag_id_base + 2, MFC_PUTB_CMD); |
153 | in += in_line_stride; |
154 | fb += out_line_stride; |
155 | deprintf("[SPU] 2nd buffer copied in=0x%x, fb=0x%x\n", in, |
156 | fb); |
157 | |
158 | /* third buffer */ |
159 | DMA_WAIT_TAG(tag_id_base + 3); |
160 | // retrieve buffer |
161 | spu_mfcdma32(buf[2], (unsigned int)in, in_line_size, |
162 | tag_id_base + 3, MFC_GETB_CMD); |
163 | DMA_WAIT_TAG(tag_id_base + 3); |
164 | // store buffer |
165 | spu_mfcdma32(buf[2], (unsigned int)fb, in_line_size, |
166 | tag_id_base + 3, MFC_PUTB_CMD); |
167 | in += in_line_stride; |
168 | fb += out_line_stride; |
169 | deprintf("[SPU] 3rd buffer copied in=0x%x, fb=0x%x\n", in, |
170 | fb); |
171 | |
172 | /* fourth buffer */ |
173 | DMA_WAIT_TAG(tag_id_base + 4); |
174 | // retrieve buffer |
175 | spu_mfcdma32(buf[3], (unsigned int)in, in_line_size, |
176 | tag_id_base + 4, MFC_GETB_CMD); |
177 | DMA_WAIT_TAG(tag_id_base + 4); |
178 | // store buffer |
179 | spu_mfcdma32(buf[3], (unsigned int)fb, in_line_size, |
180 | tag_id_base + 4, MFC_PUTB_CMD); |
181 | in += in_line_stride; |
182 | fb += out_line_stride; |
183 | deprintf("[SPU] 4th buffer copied in=0x%x, fb=0x%x\n", in, |
184 | fb); |
185 | deprintf("[SPU] Loop #%i, bounded_input_height=%i\n", i, |
186 | bounded_input_height >> 2); |
187 | } |
188 | DMA_WAIT_TAG(tag_id_base + 2); |
189 | DMA_WAIT_TAG(tag_id_base + 3); |
190 | DMA_WAIT_TAG(tag_id_base + 4); |
191 | } |
192 | |
193 | |