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.
35 #include <sys/types.h>
38 #include <sys/ioctl.h>
41 #include <sys/consio.h>
45 #include "ps3gpu_ctl.h"
46 #include "ps3gpu_mth.h"
47 #include "reset_gpu_state.h"
51 #define TEXTURE_WIDTH 512
52 #define TEXTURE_HEIGHT 512
54 #define TEXTURE_PITCH (TEXTURE_WIDTH * TEXTURE_BPP)
62 main(int argc
, char **argv
)
64 struct ps3gpu_ctl_context_allocate context_allocate
;
65 struct ps3gpu_ctl_context_free context_free
;
67 volatile uint32_t *control
;
68 volatile uint8_t *driver_info
;
69 uint32_t *fifo
, *reset_gpu
, *db
[2], *zb
, *fp
, *verts
, *tex
;
70 unsigned long fifo_handle
, reset_gpu_handle
, db_handle
[2], zb_handle
, fp_handle
, verts_handle
, tex_handle
;
71 unsigned int fifo_gaddr
, reset_gpu_gaddr
, db_gaddr
[2], zb_gaddr
, fp_gaddr
, verts_gaddr
, tex_gaddr
;
72 matrix_t mat_proj
, mat_view
, mat
;
78 fd
= open(PS3GPU_DEV_PATH
, O_RDWR
);
84 /* Create GPU context */
86 context_allocate
.vram_size
= 64; /* MB */
88 err
= ioctl(fd
, PS3GPU_CTL_CONTEXT_ALLOCATE
, &context_allocate
);
94 context_id
= context_allocate
.context_id
;
96 printf("context id %d\n", context_id
);
97 printf("control handle 0x%lx size %d\n",
98 context_allocate
.control_handle
, context_allocate
.control_size
);
99 printf("driver_info handle 0x%lx size %d\n",
100 context_allocate
.driver_info_handle
, context_allocate
.driver_info_size
);
102 /* Map control registers */
104 control
= mmap(NULL
, context_allocate
.control_size
,
105 PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, context_allocate
.control_handle
);
106 if (control
== (void *) MAP_FAILED
) {
111 /* Map driver info */
113 driver_info
= mmap(NULL
, context_allocate
.driver_info_size
,
114 PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, context_allocate
.driver_info_handle
);
115 if (driver_info
== (void *) MAP_FAILED
) {
120 printf("channel id %d\n", get_channel_id(driver_info
));
124 err
= memory_allocate(fd
, context_id
, PS3GPU_CTL_MEMORY_TYPE_GART
,
125 64 * 1024, 12, &fifo_handle
, &fifo_gaddr
, (void **) &fifo
);
127 perror("memory_allocate");
131 printf("FIFO handle 0x%lx gpu addr 0x%08x\n",
132 fifo_handle
, fifo_gaddr
);
136 err
= setup_control(fd
, context_id
, fifo_handle
, fifo_handle
, 0xdeadbabe);
138 perror("setup_control");
142 printf("FIFO put 0x%08x get 0x%08x ref 0x%08x\n",
143 control
[0x10], control
[0x11], control
[0x12]);
145 /* Allocate FIFO for resetting GPU state */
147 err
= memory_allocate(fd
, context_id
, PS3GPU_CTL_MEMORY_TYPE_GART
,
148 4 * 1024, 12, &reset_gpu_handle
, &reset_gpu_gaddr
, (void **)&reset_gpu
);
150 perror("memory_allocate");
154 printf("reset GPU state handle 0x%lx gpu addr 0x%08x\n",
155 reset_gpu_handle
, reset_gpu_gaddr
);
157 memcpy(reset_gpu
, reset_gpu_state_3d
, reset_gpu_state_3d_size
);
161 fifo
[0] = PS3GPU_MTH_HDR(0, 0, reset_gpu_gaddr
| PS3GPU_MTH_ADDR_CALL
);
162 fifo
[1] = PS3GPU_MTH_HDR(1, 0, PS3GPU_MTH_ADDR_REF
);
163 fifo
[2] = 0xcafef00d;
165 control
[0x10] = fifo_gaddr
+ 3 * sizeof(uint32_t);
167 err
= wait_fifo_idle(control
);
169 fprintf(stderr
, "FIFO timeout: put 0x%08x get 0x%08x ref 0x%08x\n",
170 control
[0x10], control
[0x11], control
[0x12]);
171 dump_fifo(stderr
, fifo
, 0x400);
175 printf("FIFO put 0x%08x get 0x%08x ref 0x%08x\n",
176 control
[0x10], control
[0x11], control
[0x12]);
178 /* Allocate display buffers */
180 err
= memory_allocate(fd
, context_id
, PS3GPU_CTL_MEMORY_TYPE_VIDEO
,
181 ROUNDUP(DISPLAY_HEIGHT
* DISPLAY_PITCH
, 4 * 1024), 12,
182 &db_handle
[0], &db_gaddr
[0], (void **) &db
[0]);
184 perror("memory_allocate");
188 printf("DB0 handle 0x%lx gpu addr 0x%08x\n",
189 db_handle
[0], db_gaddr
[0]);
191 err
= memory_allocate(fd
, context_id
, PS3GPU_CTL_MEMORY_TYPE_VIDEO
,
192 ROUNDUP(DISPLAY_HEIGHT
* DISPLAY_PITCH
, 4 * 1024), 12,
193 &db_handle
[1], &db_gaddr
[1], (void **) &db
[1]);
195 perror("memory_allocate");
199 printf("DB1 handle 0x%lx gpu addr 0x%08x\n",
200 db_handle
[1], db_gaddr
[1]);
202 /* Allocate depth buffer */
204 err
= memory_allocate(fd
, context_id
, PS3GPU_CTL_MEMORY_TYPE_VIDEO
,
205 ROUNDUP(DISPLAY_HEIGHT
* DISPLAY_PITCH
, 4 * 1024), 12,
206 &zb_handle
, &zb_gaddr
, (void **) &zb
);
208 perror("memory_allocate");
212 printf("ZB handle 0x%lx gpu addr 0x%08x\n",
213 zb_handle
, zb_gaddr
);
215 /* Allocate fragment program */
217 err
= memory_allocate(fd
, context_id
, PS3GPU_CTL_MEMORY_TYPE_VIDEO
,
218 4 * 1024, 12, &fp_handle
, &fp_gaddr
, (void **) &fp
);
220 perror("memory_allocate");
224 printf("FP handle 0x%lx gpu addr 0x%08x\n",
225 fp_handle
, fp_gaddr
);
227 /* Allocate vertices */
229 err
= memory_allocate(fd
, context_id
, PS3GPU_CTL_MEMORY_TYPE_VIDEO
,
230 4 * 1024, 12, &verts_handle
, &verts_gaddr
, (void **) &verts
);
232 perror("memory_allocate");
236 printf("VERTS handle 0x%lx gpu addr 0x%08x\n",
237 verts_handle
, verts_gaddr
);
239 /* Allocate texture */
241 err
= memory_allocate(fd
, context_id
, PS3GPU_CTL_MEMORY_TYPE_VIDEO
,
242 ROUNDUP(TEXTURE_HEIGHT
* TEXTURE_PITCH
, 4 * 1024), 12,
243 &tex_handle
, &tex_gaddr
, (void **) &tex
);
245 perror("memory_allocate");
249 printf("TEX handle 0x%lx gpu addr 0x%08x\n",
250 tex_handle
, tex_gaddr
);
252 /* Create checker texture */
254 for (i
= 0; i
< TEXTURE_HEIGHT
; i
++) {
255 for (j
= 0; j
< TEXTURE_WIDTH
; j
++) {
256 if (((i
& 0x80) == 0) ^ ((j
& 0x80) == 0))
257 *(tex
+ i
* TEXTURE_WIDTH
+ j
) = 0xff000000;
259 *(tex
+ i
* TEXTURE_WIDTH
+ j
) = 0xff00ff00;
263 /* Set display buffers */
265 err
= display_buffer_set(fd
, context_id
, 0, DISPLAY_WIDTH
, DISPLAY_HEIGHT
,
266 DISPLAY_PITCH
, db_handle
[0]);
268 perror("display_buffer_set");
272 err
= display_buffer_set(fd
, context_id
, 1, DISPLAY_WIDTH
, DISPLAY_HEIGHT
,
273 DISPLAY_PITCH
, db_handle
[1]);
275 perror("display_buffer_set");
279 const struct surface_desc surf_desc
[] = {
280 /* display buffer 0 */
282 .sd_color_loc
= { 0xfeed0000, 0xfeed0000, 0xfeed0000, 0xfeed0000 },
283 .sd_color_off
= { db_gaddr
[0], 0, 0, 0 },
284 .sd_color_pitch
= { DISPLAY_PITCH
, 64, 64, 64 },
286 .sd_color_target
= 0x1,
287 .sd_depth_loc
= 0xfeed0000,
288 .sd_depth_off
= zb_gaddr
,
289 .sd_depth_pitch
= DISPLAY_PITCH
,
293 .sd_w
= DISPLAY_WIDTH
,
294 .sd_h
= DISPLAY_HEIGHT
,
296 /* display buffer 1 */
298 .sd_color_loc
= { 0xfeed0000, 0xfeed0000, 0xfeed0000, 0xfeed0000 },
299 .sd_color_off
= { db_gaddr
[1], 0, 0, 0 },
300 .sd_color_pitch
= { DISPLAY_PITCH
, 64, 64, 64 },
302 .sd_color_target
= 0x1,
303 .sd_depth_loc
= 0xfeed0000,
304 .sd_depth_off
= zb_gaddr
,
305 .sd_depth_pitch
= DISPLAY_PITCH
,
309 .sd_w
= DISPLAY_WIDTH
,
310 .sd_h
= DISPLAY_HEIGHT
,
314 const struct texture_desc tex_desc
= {
317 .td_pitch
= TEXTURE_PITCH
,
318 .td_w
= TEXTURE_WIDTH
,
319 .td_h
= TEXTURE_HEIGHT
,
326 .td_remap
= (0x2 << 14) | (0x2 << 12) | (0x2 << 10) | (0x2 << 8) |
327 (0x3 << 6) | (0x2 << 4) | (0x1 << 2) | (0x0 << 0),
330 const uint32_t clear_color
[] = {
335 const float vp_offset
[] = { DISPLAY_WIDTH
* 0.5f
, DISPLAY_HEIGHT
* 0.5f
, 0.5f
, 0.0f
};
336 const float vp_scale
[] = { DISPLAY_WIDTH
* 0.5f
, DISPLAY_HEIGHT
* 0.5f
, 0.5f
, 0.0f
};
338 const uint32_t vertex_prg
[] = {
339 /* MOV o[7].xy, v[8].xy-- */
340 0x401f9c6c, 0x00400808, 0x0106c083, 0x60419f9c,
341 /* DP4 o[0].w, v[0], c[259] */
342 0x401f9c6c, 0x01d0300d, 0x8106c0c3, 0x60403f80,
343 /* DP4 o[0].z, v[0], c[258] */
344 0x401f9c6c, 0x01d0200d, 0x8106c0c3, 0x60405f80,
345 /* DP4 o[0].y, v[0], c[257] */
346 0x401f9c6c, 0x01d0100d, 0x8106c0c3, 0x60409f80,
347 /* DP4 o[0].x, v[0], c[256] */
348 0x401f9c6c, 0x01d0000d, 0x8106c0c3, 0x60411f81,
351 uint32_t frag_prg
[] = {
352 /* TEX R0, f[4].xy--, TEX0, 2D */
353 0x9e011700, 0xc8011c9d, 0xc8000001, 0xc8003fe1,
357 * (-0.5, -0.5) -------- (0.5, -0.5)
362 * (-0.5, 0.5) -------- (0.5, 0.5)
366 const struct vertex quad_verts
[] = {
368 { 0.5f
, -0.5f
, -1.0f
, 1.0f
, 0.0f
},
369 { -0.5f
, -0.5f
, -1.0f
, 0.0f
, 0.0f
},
370 { -0.5f
, 0.5f
, -1.0f
, 0.0f
, 1.0f
},
371 { 0.5f
, 0.5f
, -1.0f
, 1.0f
, 1.0f
},
374 err
= setup_control(fd
, context_id
, fifo_handle
, fifo_handle
, 0xdeadbabe);
376 perror("setup_control");
380 printf("FIFO put 0x%08x get 0x%08x ref 0x%08x\n",
381 control
[0x10], control
[0x11], control
[0x12]);
383 /* Transfer fragment program to VRAM */
385 err
+= transfer_inline(fifo
+ err
, 0xfeed0000, fp_gaddr
,
386 frag_prg
, ARRAY_SIZE(frag_prg
));
388 /* Transfer vertices to VRAM */
390 err
+= transfer_inline(fifo
+ err
, 0xfeed0000, verts_gaddr
,
391 (uint32_t *) quad_verts
, sizeof(quad_verts
) / sizeof(uint32_t));
393 control
[0x10] = fifo_gaddr
+ err
* sizeof(uint32_t);
395 err
= wait_fifo_idle(control
);
397 fprintf(stderr
, "FIFO timeout: put 0x%08x get 0x%08x ref 0x%08x\n",
398 control
[0x10], control
[0x11], control
[0x12]);
399 dump_fifo(stderr
, fifo
, 0x400);
403 printf("FIFO put 0x%08x get 0x%08x ref 0x%08x\n",
404 control
[0x10], control
[0x11], control
[0x12]);
406 for (i
= 0; i
< ARRAY_SIZE(surf_desc
); i
++) {
407 err
= setup_control(fd
, context_id
, fifo_handle
, fifo_handle
, 0xdeadbabe);
409 perror("setup_control");
413 printf("FIFO put 0x%08x get 0x%08x ref 0x%08x\n",
414 control
[0x10], control
[0x11], control
[0x12]);
416 err
+= set_surface(fifo
+ err
, &surf_desc
[i
]);
417 err
+= set_depth_mask(fifo
+ err
, 0x00000000);
418 err
+= set_color_mask(fifo
+ err
, 0x01010101);
419 err
+= set_color_mask_mrt(fifo
+ err
, 0x00000000);
420 err
+= set_clear_color(fifo
+ err
, clear_color
[i
]);
421 err
+= set_scissor(fifo
+ err
, 0, 0, 4095, 4095);
422 err
+= blend_enable(fifo
+ err
, 0);
423 err
+= clear_surface(fifo
+ err
, 0x000000f1);
425 err
+= set_viewport(fifo
+ err
, 0, 0, DISPLAY_WIDTH
, DISPLAY_HEIGHT
,
426 0.0f
, 1.0f
, vp_offset
, vp_scale
);
430 err
+= invalidate_texture_cache(fifo
+ err
, 0x1);
431 err
+= set_texture(fifo
+ err
, 0, &tex_desc
);
432 err
+= texture_ctrl(fifo
+ err
, 0, 1, (0 << 8), (12 << 8), 0);
433 err
+= set_texture_addr(fifo
+ err
, 0, 0x3, 0x3, 0x3, 0x0, 0x1, 0x0);
434 err
+= set_texture_filter(fifo
+ err
, 0, 0, 0x2, 0x2, 0x1);
436 /* Compute MVP matrix */
438 matrix_proj(mat_proj
, -1.0f
, 1.0f
, -1.0f
, 1.0f
, 1.0f
, 10000.0f
);
439 matrix_trans(mat_view
, 0.0f
, 0.0f
, -0.5f
);
440 MATRIX_ELEM(mat_view
, 0, 0) = 1.0f
/ (16.0f
/ 9.0f
);
441 matrix_mult(mat
, mat_proj
, mat_view
);
443 /* Set vertex shader */
445 err
+= load_vertex_prg(fifo
+ err
, 0, vertex_prg
, ARRAY_SIZE(vertex_prg
) / 4);
446 err
+= set_vertex_prg_start_slot(fifo
+ err
, 0);
447 err
+= set_vertex_prg_reg_count(fifo
+ err
, 1);
448 err
+= set_vertex_prg_const(fifo
+ err
, 256, 16, mat
);
449 err
+= set_vertex_attr_inmask(fifo
+ err
, (1 << 8) | (1 << 0));
450 err
+= set_vertex_attr_outmask(fifo
+ err
, (1 << 14));
452 /* Set fragment shader */
454 err
+= set_frag_prg(fifo
+ err
, 0x1, fp_gaddr
);
455 err
+= frag_prg_ctrl(fifo
+ err
, 2, 0, 0, 0, 0);
457 err
+= set_front_poly_mode(fifo
+ err
, 0x1b02);
458 err
+= set_shade_mode(fifo
+ err
, 0x1d01);
460 /* register 0 - position */
461 err
+= set_vertex_data_arr(fifo
+ err
, 0, 0, sizeof(struct vertex
),
462 3, 2, 0x0, verts_gaddr
+ offsetof(struct vertex
, x
));
463 /* register 8 - texture0 */
464 err
+= set_vertex_data_arr(fifo
+ err
, 8, 0, sizeof(struct vertex
),
465 2, 2, 0x0, verts_gaddr
+ offsetof(struct vertex
, u
));
467 err
+= draw_arrays(fifo
+ err
, 0x8, 0, ARRAY_SIZE(quad_verts
));
469 err
+= flip_display_buffer(fifo
+ err
, get_channel_id(driver_info
), i
, 0);
472 * Label with index 0 (head 0) is set by LV1 to 0x00000000 when flip is complete.
473 * Let GPU wait for it.
476 err
+= wait_label(fifo
+ err
, 0, 0x00000000);
478 control
[0x10] = fifo_gaddr
+ err
* sizeof(uint32_t);
480 err
= wait_fifo_idle(control
);
482 fprintf(stderr
, "FIFO timeout: put 0x%08x get 0x%08x ref 0x%08x\n",
483 control
[0x10], control
[0x11], control
[0x12]);
484 dump_fifo(stderr
, fifo
, 0x400);
488 printf("FIFO put 0x%08x get 0x%08x ref 0x%08x\n",
489 control
[0x10], control
[0x11], control
[0x12]);
494 save_image("image.argb", (const char *) db
[0], DISPLAY_PITCH
* DISPLAY_HEIGHT
);
496 /* Destroy GPU context */
498 context_free
.context_id
= context_id
;
500 err
= ioctl(fd
, PS3GPU_CTL_CONTEXT_FREE
, &context_free
);
511 /* Restore console */
513 ioctl(0, SW_TEXT_80x25
, NULL
);