2 * Copyright (C) 2011, 2012 glevand <geoffrey.levand@mail.ru>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 #include "ps3gpu_ctl.h"
38 #include "ps3gpu_mth.h"
42 save_image(const char *filename
, const char *buf
, int len
)
48 fp
= fopen(filename
, "w");
52 nwritten
= fwrite(buf
, 1, len
, fp
);
62 dump_fifo(FILE *fp
, const uint32_t *fifo
, unsigned int word_count
)
66 while (word_count
--) {
67 fprintf(fp
, "%08x: %08x\n", i
* 4, fifo
[i
]);
73 transfer_data(uint32_t *fifo
, uint32_t src
, uint32_t dst
,
74 uint32_t dst_offset
, int32_t dst_pitch
, uint32_t src_offset
, int32_t src_pitch
,
75 uint32_t row_length
, uint32_t row_count
)
80 fifo
[i
++] = PS3GPU_MTH_HDR(2, 1, 0x184);
89 fifo
[i
++] = PS3GPU_MTH_HDR(8, 1, 0x30c);
90 fifo
[i
++] = src_offset
;
91 fifo
[i
++] = dst_offset
;
92 fifo
[i
++] = src_pitch
;
93 fifo
[i
++] = dst_pitch
;
94 fifo
[i
++] = row_length
;
96 fifo
[i
++] = 0x00000101;
97 fifo
[i
++] = 0x00000000;
99 src_offset
+= h
* src_pitch
;
100 dst_offset
+= h
* dst_pitch
;
104 fifo
[i
++] = PS3GPU_MTH_HDR(1, 1, 0x310);
105 fifo
[i
++] = 0x00000000;
111 transfer_inline(uint32_t *fifo
, uint32_t dst
, uint32_t dst_offset
,
112 const uint32_t *data
, uint32_t word_count
)
114 int odd
= word_count
& 1;
117 fifo
[i
++] = PS3GPU_MTH_HDR(1, 3, 0x188);
120 fifo
[i
++] = PS3GPU_MTH_HDR(1, 3, 0x30c);
121 fifo
[i
++] = dst_offset
& ~0x3f;
123 fifo
[i
++] = PS3GPU_MTH_HDR(2, 3, 0x300);
124 fifo
[i
++] = 0x0000000b;
125 fifo
[i
++] = 0x10001000;
127 fifo
[i
++] = PS3GPU_MTH_HDR(3, 5, 0x304);
128 fifo
[i
++] = (dst_offset
>> 2) & 0xf;
129 fifo
[i
++] = 0x00010000 | word_count
;
130 fifo
[i
++] = 0x00010000 | word_count
;
132 fifo
[i
++] = PS3GPU_MTH_HDR((word_count
+ 1) & ~1, 5, 0x400);
138 fifo
[i
++] = 0x00000000;
144 flip_display_buffer(uint32_t *fifo
, uint8_t channel_id
, uint8_t buffer_id
,
149 /* reset flip label */
151 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x64);
152 fifo
[i
++]= (head
<< 4);
154 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x6c);
155 fifo
[i
++] = 0x00000001;
157 /* 0xcafebabe flip method */
159 fifo
[i
++] = PS3GPU_MTH_HDR(1, 7, 0x920 + (head
<< 2));
160 fifo
[i
++] = 0x80000000 | (channel_id
<< 8) | buffer_id
;
166 set_depth_mask(uint32_t *fifo
, uint32_t mask
)
170 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, PS3GPU_MTH_ADDR_DEPTH_MASK
);
177 set_color_mask(uint32_t *fifo
, uint32_t mask
)
181 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, PS3GPU_MTH_ADDR_COLOR_MASK
);
188 set_color_mask_mrt(uint32_t *fifo
, uint32_t mask
)
192 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, PS3GPU_MTH_ADDR_COLOR_MASK_MRT
);
199 set_clear_color(uint32_t *fifo
, uint32_t color
)
203 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, PS3GPU_MTH_ADDR_CLEAR_COLOR
);
210 set_scissor(uint32_t *fifo
, uint16_t x
, uint16_t y
, uint16_t w
, uint16_t h
)
214 fifo
[i
++] = PS3GPU_MTH_HDR(2, 0, PS3GPU_MTH_ADDR_SCISSOR
);
215 fifo
[i
++] = (w
<< 16) | x
;
216 fifo
[i
++] = (h
<< 16) | y
;
222 set_front_poly_mode(uint32_t *fifo
, uint32_t mode
)
226 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x1828);
233 set_shade_mode(uint32_t *fifo
, uint32_t mode
)
237 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x368);
244 clear_surface(uint32_t *fifo
, uint32_t mask
)
248 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x1d94);
251 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x100);
252 fifo
[i
++] = 0x00000000;
258 set_surface(uint32_t *fifo
, const struct surface_desc
*sd
)
262 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x194);
263 fifo
[i
++] = sd
->sd_color_loc
[0];
265 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x18c);
266 fifo
[i
++] = sd
->sd_color_loc
[1];
268 fifo
[i
++] = PS3GPU_MTH_HDR(2, 0, 0x1b4);
269 fifo
[i
++] = sd
->sd_color_loc
[2];
270 fifo
[i
++] = sd
->sd_color_loc
[3];
272 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x198);
273 fifo
[i
++] = sd
->sd_depth_loc
;
275 fifo
[i
++] = PS3GPU_MTH_HDR(6, 0, 0x208);
276 fifo
[i
++] = ((uint8_t) log2(sd
->sd_h
) << 24) | ((uint8_t) log2(sd
->sd_w
) << 16) |
277 (0x0 << 12) | (0x1 << 8) |
278 (sd
->sd_depth_fmt
<< 5) | sd
->sd_color_fmt
;
279 fifo
[i
++] = sd
->sd_color_pitch
[0];
280 fifo
[i
++] = sd
->sd_color_off
[0];
281 fifo
[i
++] = sd
->sd_depth_off
;
282 fifo
[i
++] = sd
->sd_color_off
[1];
283 fifo
[i
++] = sd
->sd_color_pitch
[1];
285 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x22c);
286 fifo
[i
++] = sd
->sd_depth_pitch
;
288 fifo
[i
++] = PS3GPU_MTH_HDR(4, 0, 0x280);
289 fifo
[i
++] = sd
->sd_color_pitch
[2];
290 fifo
[i
++] = sd
->sd_color_pitch
[3];
291 fifo
[i
++] = sd
->sd_color_off
[2];
292 fifo
[i
++] = sd
->sd_color_off
[3];
294 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x220);
295 fifo
[i
++] = sd
->sd_color_target
;
297 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x2b8);
298 fifo
[i
++] = (sd
->sd_y
<< 16) | sd
->sd_x
;
300 fifo
[i
++] = PS3GPU_MTH_HDR(2, 0, 0x200);
301 fifo
[i
++] = (sd
->sd_w
<< 16) | sd
->sd_x
;
302 fifo
[i
++] = (sd
->sd_h
<< 16) | sd
->sd_y
;
304 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x1d88);
305 fifo
[i
++] = (0x0 << 16) | (0x1 << 12) |
306 (sd
->sd_h
- ((sd
->sd_h
>> 12) & 0x1));
312 wait_label(uint32_t *fifo
, uint32_t index
, uint32_t val
)
316 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x64);
317 fifo
[i
++] = index
<< 4;
319 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x68);
326 set_label(uint32_t *fifo
, uint32_t index
, uint32_t val
)
330 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x64);
331 fifo
[i
++] = index
<< 4;
333 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x6c);
340 set_viewport(uint32_t *fifo
, uint16_t x
, uint16_t y
, uint16_t w
, uint16_t h
,
341 float zmin
, float zmax
, const float offset
[4], const float scale
[4])
345 fifo
[i
++] = PS3GPU_MTH_HDR(2, 0, 0xa00);
346 fifo
[i
++] = (w
<< 16) | x
;
347 fifo
[i
++] = (h
<< 16) | y
;
349 fifo
[i
++] = PS3GPU_MTH_HDR(2, 0, 0x394);
350 fifo
[i
++] = *(uint32_t *) &zmin
;
351 fifo
[i
++] = *(uint32_t *) &zmax
;
353 fifo
[i
++] = PS3GPU_MTH_HDR(8, 0, 0xa20);
354 fifo
[i
++] = *(uint32_t *) &offset
[0];
355 fifo
[i
++] = *(uint32_t *) &offset
[1];
356 fifo
[i
++] = *(uint32_t *) &offset
[2];
357 fifo
[i
++] = *(uint32_t *) &offset
[3];
358 fifo
[i
++] = *(uint32_t *) &scale
[0];
359 fifo
[i
++] = *(uint32_t *) &scale
[1];
360 fifo
[i
++] = *(uint32_t *) &scale
[2];
361 fifo
[i
++] = *(uint32_t *) &scale
[3];
363 fifo
[i
++] = PS3GPU_MTH_HDR(8, 0, 0xa20);
364 fifo
[i
++] = *(uint32_t *) &offset
[0];
365 fifo
[i
++] = *(uint32_t *) &offset
[1];
366 fifo
[i
++] = *(uint32_t *) &offset
[2];
367 fifo
[i
++] = *(uint32_t *) &offset
[3];
368 fifo
[i
++] = *(uint32_t *) &scale
[0];
369 fifo
[i
++] = *(uint32_t *) &scale
[1];
370 fifo
[i
++] = *(uint32_t *) &scale
[2];
371 fifo
[i
++] = *(uint32_t *) &scale
[3];
377 load_vertex_prg(uint32_t *fifo
, uint16_t slot
, const uint32_t *prg
, int instr_count
)
382 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x1e9c);
385 while (instr_count
>= 32) {
386 fifo
[i
++] = PS3GPU_MTH_HDR(32, 0, 0xb80);
388 for (j
= 0; j
< 32; j
++) {
398 if (instr_count
> 0) {
399 fifo
[i
++] = PS3GPU_MTH_HDR(instr_count
<< 2, 0, 0xb80);
401 for (j
= 0; j
< instr_count
; j
++) {
413 set_vertex_prg_reg_count(uint32_t *fifo
, unsigned int count
)
418 val
= (count
<= 32) ? 0x0020ffff : 0x0030ffff;
420 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x1ef8);
427 set_vertex_prg_start_slot(uint32_t *fifo
, uint16_t slot
)
431 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x1ea0);
438 set_vertex_attr_inmask(uint32_t *fifo
, uint32_t mask
)
442 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x1ff0);
449 set_vertex_attr_outmask(uint32_t *fifo
, uint32_t mask
)
453 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x1ff4);
460 set_frag_prg(uint32_t *fifo
, uint8_t location
, uint32_t offset
)
464 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x8e4);
465 fifo
[i
++] = offset
| location
;
471 frag_prg_ctrl(uint32_t *fifo
, uint8_t reg_count
, uint8_t replace_txp_with_tex
,
472 uint8_t pixel_kill
, uint8_t output_from_h0
, uint8_t depth_replace
)
482 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x1d60);
483 fifo
[i
++] = (reg_count
<< 24) | (replace_txp_with_tex
<< 15) | 0x00000400 |
484 (pixel_kill
<< 7) | (!output_from_h0
<< 6) | (depth_replace
<< 1);
490 draw_begin(uint32_t *fifo
, uint32_t mode
)
494 fifo
[i
++] = 0x40000000 | PS3GPU_MTH_HDR(3, 0, 0x1714);
495 fifo
[i
++] = 0x00000000;
496 fifo
[i
++] = 0x00000000;
497 fifo
[i
++] = 0x00000000;
499 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x1808);
506 draw_end(uint32_t *fifo
)
510 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x1808);
511 fifo
[i
++] = 0x00000000;
517 set_vertex_data_arrfmt(uint32_t *fifo
, uint8_t reg
, uint16_t freq
,
518 uint8_t stride
, uint8_t size
, uint8_t type
)
522 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x1740 + (reg
<< 4));
523 fifo
[i
++] = (freq
<< 16) | (stride
<< 8) | (size
<< 4) | type
;
529 set_vertex_data_4f(uint32_t *fifo
, uint8_t reg
, const float val
[4])
533 fifo
[i
++] = PS3GPU_MTH_HDR(4, 0, 0x1c00 + (reg
<< 4));
534 fifo
[i
++] = *(uint32_t *) &val
[0];
535 fifo
[i
++] = *(uint32_t *) &val
[1];
536 fifo
[i
++] = *(uint32_t *) &val
[2];
537 fifo
[i
++] = *(uint32_t *) &val
[3];
543 set_vertex_data_arr(uint32_t *fifo
, uint8_t reg
,
544 uint16_t freq
, uint8_t stride
, uint8_t size
, uint8_t type
,
545 uint8_t location
, uint32_t offset
)
549 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x1740 + (reg
<< 2));
550 fifo
[i
++] = (freq
<< 16) | (stride
<< 8) | (size
<< 4) | type
;
552 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x1680 + (reg
<< 2));
553 fifo
[i
++] = (location
<< 31) | offset
;
559 draw_arrays(uint32_t *fifo
, uint32_t mode
, uint32_t first
, uint32_t count
)
566 fifo
[i
++] = 0x40000000 | PS3GPU_MTH_HDR(3, 0, 0x1714);
567 fifo
[i
++] = 0x00000000;
568 fifo
[i
++] = 0x00000000;
569 fifo
[i
++] = 0x00000000;
571 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x1808);
574 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x1814);
575 fifo
[i
++] = (((count
- 1) & 0xff) << 24) | first
;
577 first
+= ((count
- 1) & 0xff) + 1;
578 count
-= ((count
- 1) & 0xff) + 1;
580 while (count
>= (0x7ff * 0x100)) {
581 fifo
[i
++] = 0x40000000 | PS3GPU_MTH_HDR(0x7ff, 0, 0x1814);
583 for (j
= 0; j
< 0x7ff; j
++) {
584 fifo
[i
++] = ((0x100 - 1) << 24) | first
;
588 count
-= 0x7ff * 0x100;
592 fifo
[i
++] = 0x40000000 | PS3GPU_MTH_HDR(count
, 0, 0x1814);
594 for (j
= 0; j
< count
; j
++) {
595 fifo
[i
++] = ((0x100 - 1) << 24) | first
;
602 fifo
[i
++] = PS3GPU_MTH_HDR(1, 0, 0x1808);
603 fifo
[i
++] = 0x00000000;