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.
34 #include <sys/types.h>
37 #include <sys/ioctl.h>
40 #include <sys/consio.h>
44 #include "ps3gpu_ctl.h"
45 #include "ps3gpu_mth.h"
47 #define PS3GPU_DEV_PATH "/dev/ps3gpu"
49 #define DISPLAY_WIDTH 1920
50 #define DISPLAY_HEIGHT 1080
52 #define DISPLAY_PITCH (DISPLAY_WIDTH * DISPLAY_BPP)
54 static uint32_t reset_gpu_state
[] = {
55 /* These commands are executed every time after flip to reset GPU state !!! */
310 0x00040310, /* blend control */
311 0x00000000, /* disable */
366 0x00041834, /* set front face mode */
367 0x00000901, /* ccw */
372 0x00040374, /* logic op control */
373 0x00000000, /* disable */
375 0x00040378, /* set logic op */
376 0x00001503, /* copy */
398 0x00040368, /* set shade model */
399 0x00001d01, /* smooth */
893 0x00020000, /* return */
896 static const uint64_t cursor_bitmap
[64] = {
964 update_cursor(int fd
, int context_id
, int head
, unsigned long offset
,
965 int x
, int y
, int enable
)
967 struct ps3gpu_ctl_cursor_enable cursor_enable
;
968 struct ps3gpu_ctl_cursor_set_image cursor_set_image
;
969 struct ps3gpu_ctl_cursor_set_position cursor_set_position
;
974 cursor_enable
.context_id
= context_id
;
975 cursor_enable
.head
= head
;
976 cursor_enable
.enable
= 0;
978 err
= ioctl(fd
, PS3GPU_CTL_CURSOR_ENABLE
, &cursor_enable
);
984 /* Set cursor image */
986 cursor_set_image
.context_id
= context_id
;
987 cursor_set_image
.head
= head
;
988 cursor_set_image
.offset
= offset
;
990 err
= ioctl(fd
, PS3GPU_CTL_CURSOR_SET_IMAGE
, &cursor_set_image
);
996 /* Set cursor position */
998 cursor_set_position
.context_id
= context_id
;
999 cursor_set_position
.head
= head
;
1000 cursor_set_position
.x
= x
;
1001 cursor_set_position
.y
= y
;
1003 err
= ioctl(fd
, PS3GPU_CTL_CURSOR_SET_POSITION
, &cursor_set_position
);
1011 cursor_enable
.context_id
= context_id
;
1012 cursor_enable
.head
= head
;
1013 cursor_enable
.enable
= enable
;
1015 err
= ioctl(fd
, PS3GPU_CTL_CURSOR_ENABLE
, &cursor_enable
);
1025 transfer_data(uint32_t *fifo
, uint32_t src
, uint32_t dst
,
1026 uint32_t dst_offset
, int32_t dst_pitch
, int32_t src_offset
, uint32_t src_pitch
,
1027 uint32_t row_length
, uint32_t row_count
)
1032 fifo
[i
++] = 0x00082184;
1041 fifo
[i
++] = 0x0020230c;
1042 fifo
[i
++] = src_offset
;
1043 fifo
[i
++] = dst_offset
;
1044 fifo
[i
++] = src_pitch
;
1045 fifo
[i
++] = dst_pitch
;
1046 fifo
[i
++] = row_length
;
1048 fifo
[i
++] = 0x00000101;
1049 fifo
[i
++] = 0x00000000;
1051 src_offset
+= h
* src_pitch
;
1052 dst_offset
+= h
* dst_pitch
;
1056 fifo
[i
++] = 0x00042310;
1057 fifo
[i
++] = 0x00000000;
1063 main(int argc
, char **argv
)
1065 struct ps3gpu_ctl_context_allocate context_allocate
;
1066 struct ps3gpu_ctl_context_free context_free
;
1067 struct ps3gpu_ctl_memory_allocate memory_allocate
;
1068 struct ps3gpu_ctl_setup_control setup_control
;
1069 struct ps3gpu_ctl_flip flip
;
1071 volatile uint32_t *control
;
1072 uint32_t *fifo
, *reset_gpu
, *vram
, *cursor
;
1073 unsigned long fifo_handle
, vram_handle
, cursor_handle
;
1074 unsigned int fifo_gaddr
, reset_gpu_gaddr
, vram_gaddr
;
1077 int x1
, y1
, x2
, y2
, w
, h
;
1080 /* Open GPU device */
1082 fd
= open(PS3GPU_DEV_PATH
, O_RDWR
);
1088 /* Create GPU context */
1090 context_allocate
.vram_size
= 64; /* MB */
1092 err
= ioctl(fd
, PS3GPU_CTL_CONTEXT_ALLOCATE
, &context_allocate
);
1098 context_id
= context_allocate
.context_id
;
1100 printf("context id %d\n", context_id
);
1101 printf("control handle 0x%lx size %d\n",
1102 context_allocate
.control_handle
, context_allocate
.control_size
);
1104 /* Map control registers */
1106 control
= mmap(NULL
, context_allocate
.control_size
,
1107 PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, context_allocate
.control_handle
);
1108 if (control
== (void *) MAP_FAILED
) {
1115 memory_allocate
.context_id
= context_id
;
1116 memory_allocate
.type
= PS3GPU_CTL_MEMORY_TYPE_GART
;
1117 memory_allocate
.size
= 64 * 1024;
1118 memory_allocate
.align
= 12;
1120 err
= ioctl(fd
, PS3GPU_CTL_MEMORY_ALLOCATE
, &memory_allocate
);
1126 fifo_handle
= memory_allocate
.handle
;
1127 fifo_gaddr
= memory_allocate
.gpu_addr
;
1129 printf("fifo handle 0x%lx gpu addr 0x08%x\n",
1130 fifo_handle
, fifo_gaddr
);
1134 fifo
= mmap(NULL
, memory_allocate
.size
,
1135 PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, fifo_handle
);
1136 if (fifo
== (void *) MAP_FAILED
) {
1143 setup_control
.context_id
= context_id
;
1144 setup_control
.put
= fifo_handle
;
1145 setup_control
.get
= fifo_handle
;
1146 setup_control
.ref
= 0xdeadbabe;
1148 err
= ioctl(fd
, PS3GPU_CTL_SETUP_CONTROL
, &setup_control
);
1154 printf("FIFO put 0x%08x get 0x%08x ref 0x%08x\n",
1155 control
[0x10], control
[0x11], control
[0x12]);
1157 /* Allocate FIFO for resetting GPU state */
1159 memory_allocate
.context_id
= context_id
;
1160 memory_allocate
.type
= PS3GPU_CTL_MEMORY_TYPE_GART
;
1161 memory_allocate
.size
= 8 * 1024;
1162 memory_allocate
.align
= 12;
1164 err
= ioctl(fd
, PS3GPU_CTL_MEMORY_ALLOCATE
, &memory_allocate
);
1170 reset_gpu_gaddr
= memory_allocate
.gpu_addr
;
1172 printf("reset GPU state handle 0x%lx gpu addr 0x%08x\n",
1173 memory_allocate
.handle
, reset_gpu_gaddr
);
1175 /* Map FIFO for resetting GPU state */
1177 reset_gpu
= mmap(NULL
, memory_allocate
.size
,
1178 PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, memory_allocate
.handle
);
1179 if (reset_gpu
== (void *) MAP_FAILED
) {
1184 memcpy(reset_gpu
, reset_gpu_state
, sizeof(reset_gpu_state
));
1188 fifo
[0] = PS3GPU_MTH_HDR(0, 0, reset_gpu_gaddr
| PS3GPU_MTH_ADDR_CALL
);
1189 fifo
[1] = PS3GPU_MTH_HDR(1, 0, PS3GPU_MTH_ADDR_REF
);
1190 fifo
[2] = 0xcafef00d;
1192 control
[0x10] = fifo_gaddr
+ 3 * sizeof(uint32_t);
1194 while (control
[0x10] != control
[0x11])
1197 printf("FIFO put 0x%08x get 0x%08x ref 0x%08x\n",
1198 control
[0x10], control
[0x11], control
[0x12]);
1202 memory_allocate
.context_id
= context_id
;
1203 memory_allocate
.type
= PS3GPU_CTL_MEMORY_TYPE_VIDEO
;
1204 memory_allocate
.size
= 9 * 1024 * 1024;
1205 memory_allocate
.align
= 12;
1207 err
= ioctl(fd
, PS3GPU_CTL_MEMORY_ALLOCATE
, &memory_allocate
);
1213 vram_handle
= memory_allocate
.handle
;
1214 vram_gaddr
= memory_allocate
.gpu_addr
;
1216 printf("VRAM handle 0x%lx gpu addr 0x%08x\n",
1217 vram_handle
, vram_gaddr
);
1221 vram
= mmap(NULL
, memory_allocate
.size
,
1222 PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, vram_handle
);
1223 if (vram
== (void *) MAP_FAILED
) {
1228 memset(vram
, 0x40, memory_allocate
.size
);
1230 /* Allocate cursor */
1232 memory_allocate
.context_id
= context_id
;
1233 memory_allocate
.type
= PS3GPU_CTL_MEMORY_TYPE_VIDEO
;
1234 memory_allocate
.size
= 16 * 1024;
1235 memory_allocate
.align
= 20;
1237 err
= ioctl(fd
, PS3GPU_CTL_MEMORY_ALLOCATE
, &memory_allocate
);
1243 cursor_handle
= memory_allocate
.handle
;
1245 printf("cursor handle 0x%lx gpu addr 0x%08x\n",
1246 cursor_handle
, memory_allocate
.gpu_addr
);
1250 cursor
= mmap(NULL
, memory_allocate
.size
,
1251 PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, cursor_handle
);
1252 if (cursor
== (void *) MAP_FAILED
) {
1257 /* Create cursor image */
1259 for (y
= 0; y
< 64; y
++) {
1260 for (x
= 0; x
< 64; x
++)
1261 if (cursor_bitmap
[(y
* 64 + x
) >> 6] &
1262 (1ul << ((63 - (y
* 64 + x
)) & 0x3f)))
1263 cursor
[y
* 64 + x
] = 0xffffff00;
1265 cursor
[y
* 64 + x
] = 0x00000000;
1270 err
= update_cursor(fd
, context_id
, PS3GPU_CTL_HEAD_A
,
1271 cursor_handle
, 100, 100, 1);
1275 err
= update_cursor(fd
, context_id
, PS3GPU_CTL_HEAD_B
,
1276 cursor_handle
, 100, 100, 1);
1282 flip
.context_id
= context_id
;
1283 flip
.head
= PS3GPU_CTL_HEAD_A
;
1284 flip
.offset
= vram_handle
;
1286 err
= ioctl(fd
, PS3GPU_CTL_FLIP
, &flip
);
1292 flip
.context_id
= context_id
;
1293 flip
.head
= PS3GPU_CTL_HEAD_B
;
1294 flip
.offset
= vram_handle
;
1296 err
= ioctl(fd
, PS3GPU_CTL_FLIP
, &flip
);
1306 err
= update_cursor(fd
, context_id
, PS3GPU_CTL_HEAD_A
,
1307 cursor_handle
, 300, 300, 1);
1309 fprintf(stderr
, "could not update cursor\n");
1313 err
= update_cursor(fd
, context_id
, PS3GPU_CTL_HEAD_B
,
1314 cursor_handle
, 300, 300, 1);
1316 fprintf(stderr
, "could not update cursor\n");
1329 for (y
= y2
; y
< y2
+ h
; y
++) {
1330 for (x
= x2
; x
< x2
+ w
; x
++) {
1331 if (y
< (y2
+ h
/ 2))
1332 vram
[y
* DISPLAY_WIDTH
+ x
] = 0x0000ff00;
1334 vram
[y
* DISPLAY_WIDTH
+ x
] = 0xffffff00;
1338 /* RSX DMA supports positive and negative pitches */
1340 /* Test positive pitch */
1342 setup_control
.context_id
= context_id
;
1343 setup_control
.put
= fifo_handle
;
1344 setup_control
.get
= fifo_handle
;
1345 setup_control
.ref
= 0xdeadbabe;
1347 err
= ioctl(fd
, PS3GPU_CTL_SETUP_CONTROL
, &setup_control
);
1356 err
= transfer_data(fifo
, 0xfeed0000, 0xfeed0000,
1357 y1
* DISPLAY_PITCH
+ x1
* DISPLAY_BPP
, DISPLAY_PITCH
,
1358 y2
* DISPLAY_PITCH
+ x2
* DISPLAY_BPP
, DISPLAY_PITCH
,
1359 w
* DISPLAY_BPP
, h
);
1361 control
[0x10] = fifo_gaddr
+ err
* sizeof(uint32_t);
1363 while (control
[0x10] != control
[0x11])
1366 printf("FIFO put 0x%08x get 0x%08x ref 0x%08x\n",
1367 control
[0x10], control
[0x11], control
[0x12]);
1369 /* Test negative pitch */
1371 setup_control
.context_id
= context_id
;
1372 setup_control
.put
= fifo_handle
;
1373 setup_control
.get
= fifo_handle
;
1374 setup_control
.ref
= 0xdeadbabe;
1376 err
= ioctl(fd
, PS3GPU_CTL_SETUP_CONTROL
, &setup_control
);
1385 err
= transfer_data(fifo
, 0xfeed0000, 0xfeed0000,
1386 (y1
+ h
- 1) * DISPLAY_PITCH
+ x1
* DISPLAY_BPP
, -1 * DISPLAY_PITCH
,
1387 (y2
+ h
- 1) * DISPLAY_PITCH
+ x2
* DISPLAY_BPP
, -1 * DISPLAY_PITCH
,
1388 w
* DISPLAY_BPP
, h
);
1390 control
[0x10] = fifo_gaddr
+ err
* sizeof(uint32_t);
1392 while (control
[0x10] != control
[0x11])
1395 printf("FIFO put 0x%08x get 0x%08x ref 0x%08x\n",
1396 control
[0x10], control
[0x11], control
[0x12]);
1400 /* Destroy GPU context */
1402 context_free
.context_id
= context_id
;
1404 err
= ioctl(fd
, PS3GPU_CTL_CONTEXT_FREE
, &context_free
);
1415 /* Restore console */
1417 ioctl(0, SW_TEXT_80x25
, NULL
);