From dbf25f514c011a5029ad4017414563895dbb2b69 Mon Sep 17 00:00:00 2001 From: glevand Date: Wed, 31 Oct 2012 20:14:39 +0000 Subject: [PATCH] add test for inline transfer --- Makefile | 6 +- inline.c | 319 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ util.c | 33 +++++++ util.h | 4 + 4 files changed, 361 insertions(+), 1 deletion(-) create mode 100644 inline.c diff --git a/Makefile b/Makefile index df159a3..bf6f7e0 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CC=gcc CFLAGS=-Wall -O2 -g LDFLAGS= -all: cursor vram_dma gart_dma +all: cursor vram_dma gart_dma inline cursor: util.o reset_gpu_state.o cursor.o $(CC) $(LDFLAGS) -o $@ util.o reset_gpu_state.o cursor.o @@ -14,6 +14,9 @@ vram_dma: util.o reset_gpu_state.o vram_dma.o gart_dma: util.o reset_gpu_state.o gart_dma.o $(CC) $(LDFLAGS) -o $@ 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 + %.o: %.c $(CC) $(CFLAGS) -c $< @@ -22,3 +25,4 @@ clean: rm -f cursor.o cursor rm -f vram_dma.o vram_dma rm -f gart_dma.o gart_dma + rm -f inline.o inline diff --git a/inline.c b/inline.c new file mode 100644 index 0000000..ffba647 --- /dev/null +++ b/inline.c @@ -0,0 +1,319 @@ +/*- + * 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_flip flip; + int context_id; + volatile uint32_t *control; + uint32_t *fifo, *reset_gpu, *vram; + unsigned long fifo_handle, vram_handle; + unsigned int fifo_gaddr, reset_gpu_gaddr, vram_gaddr; + uint32_t data[200 * 200]; + int fd = -1; + int x, y; + int w, h; + 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); + + /* 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; + } + + /* 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 = 8 * 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, reset_gpu_state_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 VRAM */ + + 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; + } + + vram_handle = memory_allocate.handle; + vram_gaddr = memory_allocate.gpu_addr; + + printf("VRAM handle 0x%lx gpu addr 0x%08x\n", + vram_handle, vram_gaddr); + + /* Map VRAM */ + + vram = mmap(NULL, memory_allocate.size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, vram_handle); + if (vram == (void *) MAP_FAILED) { + perror("mmap"); + goto done; + } + + memset(vram, 0x40, memory_allocate.size); + + /* Flip */ + + flip.context_id = context_id; + flip.head = PS3GPU_CTL_HEAD_A; + flip.offset = vram_handle; + + err = ioctl(fd, PS3GPU_CTL_FLIP, &flip); + if (err < 0) { + perror("ioctl"); + goto done; + } + + flip.context_id = context_id; + flip.head = PS3GPU_CTL_HEAD_B; + flip.offset = vram_handle; + + err = ioctl(fd, PS3GPU_CTL_FLIP, &flip); + if (err < 0) { + perror("ioctl"); + goto done; + } + + usleep(2000000); + + /* Test inline transfer */ + + 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; + } + + w = 200; + h = 1; + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + if (y < (h / 2)) + data[y * w + x] = 0x0000ff00; + else + data[y * w + x] = 0xffffff00; + } + } + + x = 200; + y = 200; + + err = transfer_inline(fifo, 0xfeed0000, + vram_gaddr + y * DISPLAY_PITCH + x * DISPLAY_BPP, + data, w * h); + + 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]); + + /* + * convert -depth 8 -size 1920x1080 rgba:image.argb \ + * -color-matrix "0 1 0 0, 0 0 1 0, 0 0 0 1, 1 0 0 0" \ + * -alpha off -background black -flatten image.jpg + */ + + save_image("image.argb", (const char *) vram, DISPLAY_PITCH * DISPLAY_HEIGHT); + + usleep(5000000); + + /* 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 fd8adc4..3032d65 100644 --- a/util.c +++ b/util.c @@ -101,3 +101,36 @@ transfer_data(uint32_t *fifo, uint32_t src, uint32_t dst, return (i); } + +int +transfer_inline(uint32_t *fifo, uint32_t dst, uint32_t dst_offset, + const uint32_t *data, uint32_t word_count) +{ + int odd = word_count & 1; + int i = 0; + + fifo[i++] = 0x00046188; + fifo[i++] = dst; + + fifo[i++] = 0x0004630c; + fifo[i++] = dst_offset & ~0x3f; + + fifo[i++] = 0x00086300; + fifo[i++] = 0x0000000b; + fifo[i++] = 0x10001000; + + fifo[i++] = 0x000ca304; + fifo[i++] = (dst_offset >> 2) & 0xf; + fifo[i++] = 0x00010000 | word_count; + fifo[i++] = 0x00010000 | word_count; + + fifo[i++] = (((word_count + 1) & ~1) << 18) | 0x0000a400; + + while (word_count--) + fifo[i++] = *data++; + + if (odd) + fifo[i++] = 0x00000000; + + return (i); +} diff --git a/util.h b/util.h index 35ea41d..54b06da 100644 --- a/util.h +++ b/util.h @@ -35,4 +35,8 @@ int transfer_data(uint32_t *fifo, uint32_t src, uint32_t dst, uint32_t dst_offset, int32_t dst_pitch, uint32_t src_offset, int32_t src_pitch, uint32_t row_length, uint32_t row_count); +int +transfer_inline(uint32_t *fifo, uint32_t dst, uint32_t dst_offset, + const uint32_t *data, uint32_t word_count); + #endif -- 2.11.4.GIT