From de9f63b74b6a2a8575770171ce739c6e41adf047 Mon Sep 17 00:00:00 2001 From: glevand Date: Tue, 20 Nov 2012 20:44:15 +0000 Subject: [PATCH] add test vertex_array --- Makefile | 7 +- vertex_array.c | 550 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 556 insertions(+), 1 deletion(-) create mode 100644 vertex_array.c diff --git a/Makefile b/Makefile index 2f0a585..4cbcb2e 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,8 @@ CFLAGS+=-DDISPLAY_PITCH=\(DISPLAY_WIDTH*DISPLAY_BPP\) LDFLAGS= LIB=-lm -all: cursor vram_dma gart_dma inline display_buffer solid triangle +all: cursor vram_dma gart_dma inline display_buffer solid triangle \ + vertex_array cursor: util.o reset_gpu_state.o cursor.o $(CC) $(LDFLAGS) -o $@ util.o reset_gpu_state.o cursor.o $(LIB) @@ -30,6 +31,9 @@ solid: util.o reset_gpu_state.o solid.o triangle: util.o reset_gpu_state.o triangle.o $(CC) $(LDFLAGS) -o $@ util.o reset_gpu_state.o triangle.o $(LIB) +vertex_array: util.o reset_gpu_state.o vertex_array.o + $(CC) $(LDFLAGS) -o $@ util.o reset_gpu_state.o vertex_array.o $(LIB) + %.o: %.c $(CC) $(CFLAGS) -c $< @@ -42,3 +46,4 @@ clean: rm -f display_buffer.o display_buffer rm -f solid.o solid rm -f triangle.o triangle + rm -f vertex_array.o vertex_array diff --git a/vertex_array.c b/vertex_array.c new file mode 100644 index 0000000..34cb69e --- /dev/null +++ b/vertex_array.c @@ -0,0 +1,550 @@ +/*- + * Copyright (C) 2011, 2012 glevand + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ps3gpu_ctl.h" +#include "ps3gpu_mth.h" +#include "reset_gpu_state.h" +#include "util.h" + +struct vertex { + float x, y, z; + uint32_t rgba; +}; + +int +main(int argc, char **argv) +{ + struct ps3gpu_ctl_context_allocate context_allocate; + struct ps3gpu_ctl_context_free context_free; + struct ps3gpu_ctl_memory_allocate memory_allocate; + struct ps3gpu_ctl_setup_control setup_control; + struct ps3gpu_ctl_display_buffer_set display_buffer_set; + int context_id; + volatile uint32_t *control; + volatile uint8_t *driver_info; + uint32_t *fifo, *reset_gpu, *db[2], *zb, *fp, *verts; + unsigned long fifo_handle, db_handle[2], zb_handle, fp_handle, verts_handle; + unsigned int fifo_gaddr, reset_gpu_gaddr, db_gaddr[2], zb_gaddr, fp_gaddr, verts_gaddr; + int fd = -1; + int i, err; + + /* Open GPU device */ + + fd = open(PS3GPU_DEV_PATH, O_RDWR); + if (fd < 0) { + perror("open"); + goto done; + } + + /* Create GPU context */ + + context_allocate.vram_size = 64; /* MB */ + + err = ioctl(fd, PS3GPU_CTL_CONTEXT_ALLOCATE, &context_allocate); + if (err < 0) { + perror("ioctl"); + goto done; + } + + context_id = context_allocate.context_id; + + printf("context id %d\n", context_id); + printf("control handle 0x%lx size %d\n", + context_allocate.control_handle, context_allocate.control_size); + printf("driver_info handle 0x%lx size %d\n", + context_allocate.driver_info_handle, context_allocate.driver_info_size); + + /* Map control registers */ + + control = mmap(NULL, context_allocate.control_size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, context_allocate.control_handle); + if (control == (void *) MAP_FAILED) { + perror("mmap"); + goto done; + } + + /* Map driver info */ + + driver_info = mmap(NULL, context_allocate.driver_info_size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, context_allocate.driver_info_handle); + if (driver_info == (void *) MAP_FAILED) { + perror("mmap"); + goto done; + } + + printf("channel id %d\n", get_channel_id(driver_info)); + + /* Allocate FIFO */ + + memory_allocate.context_id = context_id; + memory_allocate.type = PS3GPU_CTL_MEMORY_TYPE_GART; + memory_allocate.size = 64 * 1024; + memory_allocate.align = 12; + + err = ioctl(fd, PS3GPU_CTL_MEMORY_ALLOCATE, &memory_allocate); + if (err < 0) { + perror("ioctl"); + goto done; + } + + fifo_handle = memory_allocate.handle; + fifo_gaddr = memory_allocate.gpu_addr; + + printf("fifo handle 0x%lx gpu addr 0x%08x\n", + fifo_handle, fifo_gaddr); + + /* Map FIFO */ + + fifo = mmap(NULL, memory_allocate.size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, fifo_handle); + if (fifo == (void *) MAP_FAILED) { + perror("mmap"); + goto done; + } + + /* Setup FIFO */ + + setup_control.context_id = context_id; + setup_control.put = fifo_handle; + setup_control.get = fifo_handle; + setup_control.ref = 0xdeadbabe; + + err = ioctl(fd, PS3GPU_CTL_SETUP_CONTROL, &setup_control); + if (err < 0) { + perror("ioctl"); + goto done; + } + + printf("FIFO put 0x%08x get 0x%08x ref 0x%08x\n", + control[0x10], control[0x11], control[0x12]); + + /* Allocate FIFO for resetting GPU state */ + + memory_allocate.context_id = context_id; + memory_allocate.type = PS3GPU_CTL_MEMORY_TYPE_GART; + memory_allocate.size = 4 * 1024; + memory_allocate.align = 12; + + err = ioctl(fd, PS3GPU_CTL_MEMORY_ALLOCATE, &memory_allocate); + if (err < 0) { + perror("ioctl"); + goto done; + } + + reset_gpu_gaddr = memory_allocate.gpu_addr; + + printf("reset GPU state handle 0x%lx gpu addr 0x%08x\n", + memory_allocate.handle, reset_gpu_gaddr); + + /* Map FIFO for resetting GPU state */ + + reset_gpu = mmap(NULL, memory_allocate.size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, memory_allocate.handle); + if (reset_gpu == (void *) MAP_FAILED) { + perror("mmap"); + goto done; + } + + memcpy(reset_gpu, reset_gpu_state_3d, reset_gpu_state_3d_size); + + /* Kick FIFO */ + + fifo[0] = PS3GPU_MTH_HDR(0, 0, reset_gpu_gaddr | PS3GPU_MTH_ADDR_CALL); + fifo[1] = PS3GPU_MTH_HDR(1, 0, PS3GPU_MTH_ADDR_REF); + fifo[2] = 0xcafef00d; + + control[0x10] = fifo_gaddr + 3 * sizeof(uint32_t); + + err = wait_fifo_idle(control); + if (err < 0) { + fprintf(stderr, "FIFO timeout: put 0x%08x get 0x%08x ref 0x%08x\n", + control[0x10], control[0x11], control[0x12]); + dump_fifo(stderr, fifo, 0x400); + goto done; + } + + printf("FIFO put 0x%08x get 0x%08x ref 0x%08x\n", + control[0x10], control[0x11], control[0x12]); + + /* Allocate display buffers */ + + memory_allocate.context_id = context_id; + memory_allocate.type = PS3GPU_CTL_MEMORY_TYPE_VIDEO; + memory_allocate.size = ROUNDUP(DISPLAY_HEIGHT * DISPLAY_PITCH, 4 * 1024); + memory_allocate.align = 12; + + err = ioctl(fd, PS3GPU_CTL_MEMORY_ALLOCATE, &memory_allocate); + if (err < 0) { + perror("ioctl"); + goto done; + } + + db_handle[0] = memory_allocate.handle; + db_gaddr[0] = memory_allocate.gpu_addr; + + printf("DB0 handle 0x%lx gpu addr 0x%08x\n", + db_handle[0], db_gaddr[0]); + + db[0] = mmap(NULL, memory_allocate.size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, db_handle[0]); + if (db[0] == (void *) MAP_FAILED) { + perror("mmap"); + goto done; + } + + memory_allocate.context_id = context_id; + memory_allocate.type = PS3GPU_CTL_MEMORY_TYPE_VIDEO; + memory_allocate.size = ROUNDUP(DISPLAY_HEIGHT * DISPLAY_PITCH, 4 * 1024); + memory_allocate.align = 12; + + err = ioctl(fd, PS3GPU_CTL_MEMORY_ALLOCATE, &memory_allocate); + if (err < 0) { + perror("ioctl"); + goto done; + } + + db_handle[1] = memory_allocate.handle; + db_gaddr[1] = memory_allocate.gpu_addr; + + printf("DB1 handle 0x%lx gpu addr 0x%08x\n", + db_handle[1], db_gaddr[1]); + + db[1] = mmap(NULL, memory_allocate.size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, db_handle[1]); + if (db[1] == (void *) MAP_FAILED) { + perror("mmap"); + goto done; + } + + /* Allocate depth buffer */ + + memory_allocate.context_id = context_id; + memory_allocate.type = PS3GPU_CTL_MEMORY_TYPE_VIDEO; + memory_allocate.size = ROUNDUP(DISPLAY_HEIGHT * DISPLAY_PITCH, 4 * 1024); + memory_allocate.align = 12; + + err = ioctl(fd, PS3GPU_CTL_MEMORY_ALLOCATE, &memory_allocate); + if (err < 0) { + perror("ioctl"); + goto done; + } + + zb_handle = memory_allocate.handle; + zb_gaddr = memory_allocate.gpu_addr; + + printf("ZB handle 0x%lx gpu addr 0x%08x\n", + zb_handle, zb_gaddr); + + zb = mmap(NULL, memory_allocate.size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, zb_handle); + if (zb == (void *) MAP_FAILED) { + perror("mmap"); + goto done; + } + + /* Allocate fragment program */ + + memory_allocate.context_id = context_id; + memory_allocate.type = PS3GPU_CTL_MEMORY_TYPE_VIDEO; + memory_allocate.size = 4 * 1024; + memory_allocate.align = 12; + + err = ioctl(fd, PS3GPU_CTL_MEMORY_ALLOCATE, &memory_allocate); + if (err < 0) { + perror("ioctl"); + goto done; + } + + fp_handle = memory_allocate.handle; + fp_gaddr = memory_allocate.gpu_addr; + + printf("FP handle 0x%lx gpu addr 0x%08x\n", + fp_handle, fp_gaddr); + + fp = mmap(NULL, memory_allocate.size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, fp_handle); + if (fp == (void *) MAP_FAILED) { + perror("mmap"); + goto done; + } + + /* Allocate vertices */ + + memory_allocate.context_id = context_id; + memory_allocate.type = PS3GPU_CTL_MEMORY_TYPE_VIDEO; + memory_allocate.size = 4 * 1024; + memory_allocate.align = 12; + + err = ioctl(fd, PS3GPU_CTL_MEMORY_ALLOCATE, &memory_allocate); + if (err < 0) { + perror("ioctl"); + goto done; + } + + verts_handle = memory_allocate.handle; + verts_gaddr = memory_allocate.gpu_addr; + + printf("VERTS handle 0x%lx gpu addr 0x%08x\n", + verts_handle, verts_gaddr); + + verts = mmap(NULL, memory_allocate.size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, verts_handle); + if (verts == (void *) MAP_FAILED) { + perror("mmap"); + goto done; + } + + /* Set display buffers */ + + display_buffer_set.context_id = context_id; + display_buffer_set.buffer_id = 0; + display_buffer_set.width = DISPLAY_WIDTH; + display_buffer_set.height = DISPLAY_HEIGHT; + display_buffer_set.pitch = DISPLAY_PITCH; + display_buffer_set.offset = db_handle[0]; + + err = ioctl(fd, PS3GPU_CTL_DISPLAY_BUFFER_SET, &display_buffer_set); + if (err < 0) { + perror("ioctl"); + goto done; + } + + display_buffer_set.context_id = context_id; + display_buffer_set.buffer_id = 1; + display_buffer_set.width = DISPLAY_WIDTH; + display_buffer_set.height = DISPLAY_HEIGHT; + display_buffer_set.pitch = DISPLAY_PITCH; + display_buffer_set.offset = db_handle[1]; + + err = ioctl(fd, PS3GPU_CTL_DISPLAY_BUFFER_SET, &display_buffer_set); + if (err < 0) { + perror("ioctl"); + goto done; + } + + const struct surface_desc surf_desc[] = { + /* display buffer 0 */ + { + .sd_color_loc = { 0xfeed0000, 0xfeed0000, 0xfeed0000, 0xfeed0000 }, + .sd_color_off = { db_gaddr[0], 0, 0, 0 }, + .sd_color_pitch = { DISPLAY_PITCH, 64, 64, 64 }, + .sd_color_fmt = 0x8, + .sd_color_target = 0x1, + .sd_depth_loc = 0xfeed0000, + .sd_depth_off = zb_gaddr, + .sd_depth_pitch = DISPLAY_PITCH, + .sd_depth_fmt = 0x2, + .sd_x = 0, + .sd_y = 0, + .sd_w = DISPLAY_WIDTH, + .sd_h = DISPLAY_HEIGHT, + }, + /* display buffer 1 */ + { + .sd_color_loc = { 0xfeed0000, 0xfeed0000, 0xfeed0000, 0xfeed0000 }, + .sd_color_off = { db_gaddr[1], 0, 0, 0 }, + .sd_color_pitch = { DISPLAY_PITCH, 64, 64, 64 }, + .sd_color_fmt = 0x8, + .sd_color_target = 0x1, + .sd_depth_loc = 0xfeed0000, + .sd_depth_off = zb_gaddr, + .sd_depth_pitch = DISPLAY_PITCH, + .sd_depth_fmt = 0x2, + .sd_x = 0, + .sd_y = 0, + .sd_w = DISPLAY_WIDTH, + .sd_h = DISPLAY_HEIGHT, + }, + }; + + const uint32_t clear_color[] = { + 0xff404040, + 0xffffffff, + }; + + const float vp_offset[] = { DISPLAY_WIDTH * 0.5f, DISPLAY_HEIGHT * 0.5f, 0.5f, 0.0f }; + const float vp_scale[] = { DISPLAY_WIDTH * 0.5f, DISPLAY_HEIGHT * 0.5f, 0.5f, 0.0f }; + + const uint32_t vertex_prg[] = { + /* MOV o[0], v[0] */ + 0x401f9c6c, 0x0040000d, 0x8106c083, 0x6041ff80, + /* MOV o[1], v[3] */ + 0x401f9c6c, 0x0040030d, 0x8106c083, 0x6041ff85, + }; + + uint32_t frag_prg[] = { + /* MOVR R0, f[1] */ + 0x01003e01, 0x1c9dc801, 0x0001c800, 0x3fe1c800, + }; + + /* + * (0.0, -0.5) + * /\ + * / \ + * / \ + * / \ + * (-0.5, 0.5) /________\ (0.5, 0.5) + * + */ + + const struct vertex triangle_verts[] = { + { 0.0f, -0.5f, -1.0f, 0xff0000ff }, + { -0.5f, 0.5f, -1.0f, 0x00ff00ff }, + { 0.5f, 0.5f, -1.0f, 0x0000ffff }, + }; + + /* Swap half-words in fragment program */ + + for (i = 0; i < ARRAY_SIZE(frag_prg); i++) + frag_prg[i] = (frag_prg[i] << 16) | (frag_prg[i] >> 16); + + for (i = 0; i < ARRAY_SIZE(surf_desc); i++) { + setup_control.context_id = context_id; + setup_control.put = fifo_handle; + setup_control.get = fifo_handle; + setup_control.ref = 0xdeadbabe; + + err = ioctl(fd, PS3GPU_CTL_SETUP_CONTROL, &setup_control); + if (err < 0) { + perror("ioctl"); + goto done; + } + + printf("FIFO put 0x%08x get 0x%08x ref 0x%08x\n", + control[0x10], control[0x11], control[0x12]); + + err += set_surface(fifo + err, &surf_desc[i]); + err += set_depth_mask(fifo + err, 0x00000000); + err += set_color_mask(fifo + err, 0x01010101); + err += set_color_mask_mrt(fifo + err, 0x00000000); + err += set_clear_color(fifo + err, clear_color[i]); + err += set_scissor(fifo + err, 0, 0, 4095, 4095); + err += clear_surface(fifo + err, 0x000000f1); + + err += set_viewport(fifo + err, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, + 0.0f, 1.0f, vp_offset, vp_scale); + + /* Set vertex shader */ + + err += load_vertex_prg(fifo + err, 0, vertex_prg, ARRAY_SIZE(vertex_prg) / 4); + err += set_vertex_prg_start_slot(fifo + err, 0); + err += set_vertex_prg_reg_count(fifo + err, 2); + err += set_vertex_attr_inmask(fifo + err, (1 << 3) | (1 << 0)); + err += set_vertex_attr_outmask(fifo + err, (1 << 2) | (1 << 0)); + + /* Transfer fragment program to VRAM */ + + err += transfer_inline(fifo + err, 0xfeed0000, fp_gaddr, + frag_prg, ARRAY_SIZE(frag_prg)); + + /* Set fragment shader */ + + err += set_frag_prg(fifo + err, 0x1, fp_gaddr); + err += frag_prg_ctrl(fifo + err, 2, 0, 0, 0, 0); + + err += set_front_poly_mode(fifo + err, 0x1b02); + err += set_shade_mode(fifo + err, 0x1d01); + + /* Transfer vertices to VRAM */ + + err += transfer_inline(fifo + err, 0xfeed0000, verts_gaddr, + (uint32_t *) triangle_verts, sizeof(triangle_verts) / sizeof(uint32_t)); + + /* register 0 - position */ + err += set_vertex_data_arr(fifo + err, 0, 0, sizeof(struct vertex), + 3, 2, verts_gaddr + offsetof(struct vertex, x), 0x0); + /* register 3 - color */ + err += set_vertex_data_arr(fifo + err, 3, 0, sizeof(struct vertex), + 4, 4, verts_gaddr + offsetof(struct vertex, rgba), 0x0); + + err += draw_arrays(fifo + err, 0x5, 0, ARRAY_SIZE(triangle_verts)); + + err += flip_display_buffer(fifo + err, get_channel_id(driver_info), i, 0); + + /* + * Label with index 0 (head 0) is set by LV1 to 0x00000000 when flip is complete. + * Let GPU wait for it. + */ + + err += wait_label(fifo + err, 0, 0x00000000); + + control[0x10] = fifo_gaddr + err * sizeof(uint32_t); + + err = wait_fifo_idle(control); + if (err < 0) { + fprintf(stderr, "FIFO timeout: put 0x%08x get 0x%08x ref 0x%08x\n", + control[0x10], control[0x11], control[0x12]); + dump_fifo(stderr, fifo, 0x400); + goto done; + } + + printf("FIFO put 0x%08x get 0x%08x ref 0x%08x\n", + control[0x10], control[0x11], control[0x12]); + + usleep(1000000); + } + + save_image("image.argb", (const char *) db[0], DISPLAY_PITCH * DISPLAY_HEIGHT); + + /* Destroy GPU context */ + + context_free.context_id = context_id; + + err = ioctl(fd, PS3GPU_CTL_CONTEXT_FREE, &context_free); + if (err < 0) { + perror("ioctl"); + goto done; + } + +done: + + if (fd >= 0) + close(fd); + + /* Restore console */ + + ioctl(0, SW_TEXT_80x25, NULL); + + exit(0); +} -- 2.11.4.GIT