From e6fa52642855321e0de793993c9660a9262e577b Mon Sep 17 00:00:00 2001 From: glevand Date: Thu, 1 Nov 2012 20:31:43 +0000 Subject: [PATCH] add display buffer test, it shows how to allocate, set and flip display buffers --- Makefile | 6 +- display_buffer.c | 365 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ util.c | 18 +++ util.h | 10 ++ 4 files changed, 398 insertions(+), 1 deletion(-) create mode 100644 display_buffer.c diff --git a/Makefile b/Makefile index bf6f7e0..59caddf 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CC=gcc CFLAGS=-Wall -O2 -g LDFLAGS= -all: cursor vram_dma gart_dma inline +all: cursor vram_dma gart_dma inline display_buffer cursor: util.o reset_gpu_state.o cursor.o $(CC) $(LDFLAGS) -o $@ util.o reset_gpu_state.o cursor.o @@ -17,6 +17,9 @@ gart_dma: util.o reset_gpu_state.o gart_dma.o inline: util.o reset_gpu_state.o inline.o $(CC) $(LDFLAGS) -o $@ util.o reset_gpu_state.o inline.o +display_buffer: util.o reset_gpu_state.o display_buffer.o + $(CC) $(LDFLAGS) -o $@ util.o reset_gpu_state.o display_buffer.o + %.o: %.c $(CC) $(CFLAGS) -c $< @@ -26,3 +29,4 @@ clean: rm -f vram_dma.o vram_dma rm -f gart_dma.o gart_dma rm -f inline.o inline + rm -f display_buffer.o display_buffer diff --git a/display_buffer.c b/display_buffer.c new file mode 100644 index 0000000..9e873e4 --- /dev/null +++ b/display_buffer.c @@ -0,0 +1,365 @@ +/*- + * 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 "ps3gpu_ctl.h" +#include "ps3gpu_mth.h" +#include "reset_gpu_state.h" +#include "util.h" + +#define PS3GPU_DEV_PATH "/dev/ps3gpu" + +#define DISPLAY_WIDTH 1920 +#define DISPLAY_HEIGHT 1080 +#define DISPLAY_BPP 4 +#define DISPLAY_PITCH (DISPLAY_WIDTH * DISPLAY_BPP) + +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]; + unsigned long fifo_handle, db_handle[2]; + unsigned int fifo_gaddr, reset_gpu_gaddr, db_gaddr[2]; + int fd = -1; + int x, y; + int 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 0x08%x\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); + + while (control[0x10] != control[0x11]) + usleep(1000); + + 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 = 9 * 1024 * 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; + } + + for (y = 0; y < DISPLAY_HEIGHT; y++) { + for (x = 0; x < DISPLAY_WIDTH; x++) + *(uint32_t *) (db[0] + y * DISPLAY_WIDTH + x) = 0x0000ff00; + } + + memory_allocate.context_id = context_id; + memory_allocate.type = PS3GPU_CTL_MEMORY_TYPE_VIDEO; + memory_allocate.size = 9 * 1024 * 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; + } + + for (y = 0; y < DISPLAY_HEIGHT; y++) { + for (x = 0; x < DISPLAY_WIDTH; x++) + *(uint32_t *) (db[1] + y * DISPLAY_WIDTH + x) = 0xffffff00; + } + + /* 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; + } + + /* Flip display buffer 0 */ + + 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; + } + + err = flip_display_buffer(fifo, get_channel_id(driver_info), 0, 0); + + control[0x10] = fifo_gaddr + err * sizeof(uint32_t); + + while (control[0x10] != control[0x11]) + usleep(1000); + + printf("FIFO put 0x%08x get 0x%08x ref 0x%08x\n", + control[0x10], control[0x11], control[0x12]); + + usleep(3000000); + + /* Flip display buffer 1 */ + + 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; + } + + err = flip_display_buffer(fifo, get_channel_id(driver_info), 1, 0); + + control[0x10] = fifo_gaddr + err * sizeof(uint32_t); + + while (control[0x10] != control[0x11]) + usleep(1000); + + printf("FIFO put 0x%08x get 0x%08x ref 0x%08x\n", + control[0x10], control[0x11], control[0x12]); + + usleep(3000000); + + /* 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); +} diff --git a/util.c b/util.c index 7cb3df7..e994f6a 100644 --- a/util.c +++ b/util.c @@ -134,3 +134,21 @@ transfer_inline(uint32_t *fifo, uint32_t dst, uint32_t dst_offset, return (i); } + +int +flip_display_buffer(uint32_t *fifo, uint8_t channel_id, uint8_t buffer_id, + uint8_t head) +{ + int i = 0; + + fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x64); + fifo[i++]= (head << 4); + + fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x6c); + fifo[i++] = 0x00000001; + + fifo[i++] = PS3GPU_MTH_HDR(1, 7, 0x920 + (head << 2)); + fifo[i++] = 0x80000000 | (channel_id << 8) | buffer_id; + + return (i); +} diff --git a/util.h b/util.h index 54b06da..ffde5d8 100644 --- a/util.h +++ b/util.h @@ -29,6 +29,12 @@ #ifndef _UTIL_H #define _UTIL_H +uint32_t +get_channel_id(const volatile void *driver_info) +{ + return (*(uint32_t *) ((uint8_t *) driver_info + 0xc)); +} + int save_image(const char *filename, const char *buf, int len); int transfer_data(uint32_t *fifo, uint32_t src, uint32_t dst, @@ -39,4 +45,8 @@ int transfer_inline(uint32_t *fifo, uint32_t dst, uint32_t dst_offset, const uint32_t *data, uint32_t word_count); +int +flip_display_buffer(uint32_t *fifo, uint8_t channel_id, uint8_t buffer_id, + uint8_t head); + #endif -- 2.11.4.GIT