annotate src/video/ps3/spulibs/fb_writer.c @ 4165:3b8ac3d311a2 SDL-1.2

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