main: draw rotating cube

This commit is contained in:
Zack Buhman 2025-09-17 14:08:07 -05:00
parent 74d3b5183b
commit 744dc8645a
2 changed files with 220 additions and 8 deletions

View File

@ -5,4 +5,4 @@
python gen/rgb_txt.py $< > $@
main: main.c bear.rgb565.inc panda.rgb565.inc
gcc -g -Og -std=c23 $< -o $@
gcc -g -Og -lm -std=gnu23 $< -o $@

226
main.c
View File

@ -6,6 +6,7 @@
#include <unistd.h>
#include <assert.h>
#include <fcntl.h>
#include <math.h>
#include "voodoo2.h"
#include "voodoo2_bits.h"
@ -16,7 +17,27 @@
static inline bool _wait_graphics_busy(voodoo2_reg * voodoo2)
{
int cnt = 0;
for (int i = 0; i < 4096; i++) {
for (int i = 0; i < 128; i++) {
if (voodoo2->status & STATUS__CHUCK_BUSY) {
//if (voodoo2->status & STATUS__PCI_FIFO_FREESPACE(0x3f)) {
cnt = 0;
} else {
cnt += 1;
}
if (cnt >= 5)
return true;
}
//fprintf(stderr, "voodoo2 status %08x\n", voodoo2->status);
//return false;
return true;
}
#define wait_graphics_busy(voodoo2) assert(_wait_graphics_busy(voodoo2));
static inline bool _wait_graphics_busy2(voodoo2_reg * voodoo2)
{
int cnt = 0;
while (true) {
if (voodoo2->status & STATUS__CHUCK_BUSY) {
cnt = 0;
} else {
@ -28,7 +49,7 @@ static inline bool _wait_graphics_busy(voodoo2_reg * voodoo2)
return false;
}
#define wait_graphics_busy(voodoo2) assert(_wait_graphics_busy(voodoo2));
#define wait_graphics_busy2(voodoo2) assert(_wait_graphics_busy2(voodoo2));
static inline void dac_data_read(voodoo2_reg * voodoo2,
int data,
@ -137,6 +158,93 @@ void write_fd_u32(int fd, uint32_t offset, uint32_t value)
assert(len == 4);
}
typedef struct vec3 {
float x;
float y;
float z;
} vec3;
static const vec3 cube_vertex_position[] = {
{ 1.0f, 1.0f, -1.0f },
{ 1.0f, -1.0f, -1.0f },
{ 1.0f, 1.0f, 1.0f },
{ 1.0f, -1.0f, 1.0f },
{ -1.0f, 1.0f, -1.0f },
{ -1.0f, -1.0f, -1.0f },
{ -1.0f, 1.0f, 1.0f },
{ -1.0f, -1.0f, 1.0f },
};
static const uint32_t cube_vertex_color[] = {
0xff0000, // red
0x00ff00, // green
0x0000ff, // blue
0xffff00, // yellow
0x00ffff, // cyan
0xff00ff, // magenta
0xff7f00, // orange
0x7f00ff, // violet
};
typedef struct face {
int a;
int b;
int c;
} face;
static const face cube_faces[] = {
{4, 2, 0},
{2, 7, 3},
{6, 5, 7},
{1, 7, 5},
{0, 3, 1},
{4, 1, 5},
{4, 6, 2},
{2, 6, 7},
{6, 4, 5},
{1, 3, 7},
{0, 2, 3},
{4, 0, 1},
};
static const int cube_faces_length = (sizeof (cube_faces)) / (sizeof (cube_faces[0]));
static float theta = 0;
static inline vec3 vertex_rotate(vec3 v)
{
// to make the cube's appearance more interesting, rotate the vertex on two
// axes
float x0 = v.x;
float y0 = v.y;
float z0 = v.z;
float x1 = x0 * cos(theta) - z0 * sin(theta);
float y1 = y0;
float z1 = x0 * sin(theta) + z0 * cos(theta);
float x2 = x1;
float y2 = y1 * cos(theta) - z1 * sin(theta);
float z2 = y1 * sin(theta) + z1 * cos(theta);
return (vec3){x2, y2, z2};
}
static inline vec3 vertex_perspective_divide(vec3 v)
{
float w = 1.0f / (v.z + 3.0f);
return (vec3){v.x * w, v.y * w, w};
}
static inline vec3 vertex_screen_space(vec3 v)
{
return (vec3){
v.x * 300.f + 400.f,
v.y * 300.f + 300.f,
v.z,
};
}
int main()
{
const char * config_path = "/sys/bus/pci/devices/0000:02:0a.0/config";
@ -180,6 +288,8 @@ int main()
int init_enable;
goto draw;
////////////////////////////////////////////////////////////////////////
// reset
////////////////////////////////////////////////////////////////////////
@ -283,6 +393,7 @@ int main()
| FBIINIT2__ENABLE_GENERATED_DRAM_OE_SIGNAL
| FBIINIT2__VIDEO_BUFFER_OFFSET(247)
| FBIINIT2__ENABLE_DRAM_READ_AHEAD_FIFO
| FBIINIT2__ENABLE_DRAM_BANKING
| FBIINIT2__REFRESH_ENABLE
| FBIINIT2__REFRESH_LOAD_VALUE(0x30)
;
@ -360,6 +471,7 @@ int main()
wait_graphics_busy(voodoo2);
if (0) {
/*
static const uint16_t panda[] __attribute__((aligned(4))) = {
#include "panda.rgb565.inc"
};
@ -388,23 +500,123 @@ int main()
}
sleep(1);
}
*/
}
////////////////////////////////////////////////////////////////////////
// triangle
////////////////////////////////////////////////////////////////////////
draw:
voodoo2->fbzMode
= FBZMODE__DEPTH_BUFFER_FUNCTION__LESS_THAN
| FBZMODE__ENABLE_DEPTH_BUFFERING
| FBZMODE__FLOATING_POINT_DEPTH_BUFFER
| FBZMODE__RGB_BUFFER_WRITE_MASK
| FBZMODE__DEPTH_ALPHA_BUFFER_WRITE_MASK
| FBZMODE__DRAW_BUFFER__BACK_BUFFER
;
wait_graphics_busy(voodoo2);
voodoo2->lfbMode
= LFBMODE__LINEAR_FRAME_BUFFER__WRITE_FORMAT__RGB565
| LFBMODE__LINEAR_FRAME_BUFFER__WRITE_BUFFER_SELECT__BACK_BUFFER
| LFBMODE__LINEAR_FRAME_BUFFER__READ_BUFFER_SELECT__FRONT_BUFFER
| LFBMODE__LINEAR_FRAME_BUFFER__ENABLE_PIXEL_PIPELINE_WRITES
| LFBMODE__LINEAR_FRAME_BUFFER__RGBA_LANES__ARGB
;
wait_graphics_busy(voodoo2);
voodoo2->sSetupMode
= SSETUPMODE__SETUP_RED_GREEN_BLUE
| SSETUPMODE__SETUP_WB
;
wait_graphics_busy(voodoo2);
//
voodoo2->clipLeftRight
= CLIPLEFTRIGHT__RIGHT(800)
| CLIPLEFTRIGHT__LEFT(0);
wait_graphics_busy(voodoo2);
voodoo2->clipLowYHighY
= CLIPLOWYHIGHY__HIGH_Y(600)
| CLIPLOWYHIGHY__LOW_Y(0);
wait_graphics_busy(voodoo2);
voodoo2->color1 = 0xff008080;
wait_graphics_busy(voodoo2);
voodoo2->zaColor
= ZACOLOR__DEPTH(0xffff)
| ZACOLOR__ALPHA(0xff)
;
voodoo2->sBeginTriCMD = 1;
for (int i = 0; i < 601; i++) {
/*
volatile uint16_t * framebuffer
= (volatile uint16_t * )(((ptrdiff_t)resource0_base) + 0x0400000);
voodoo2->sVx = 10;
voodoo2->sVy = 10;
voodoo2->sVy = 10;
for (int i = 0; i < 1024 * 800 * 2 / 2; i++) {
framebuffer[i] = 0;
}
wait_graphics_busy(voodoo2);
*/
voodoo2->sDrawTriCMD = 1;
voodoo2->fastfillCMD = 0;
wait_graphics_busy2(voodoo2);
for (int face_ix = 0; face_ix < cube_faces_length; face_ix++) {
int ia = cube_faces[face_ix].a;
int ib = cube_faces[face_ix].b;
int ic = cube_faces[face_ix].c;
vec3 va = vertex_screen_space(
vertex_perspective_divide(
vertex_rotate(cube_vertex_position[ia])));
vec3 vb = vertex_screen_space(
vertex_perspective_divide(
vertex_rotate(cube_vertex_position[ib])));
vec3 vc = vertex_screen_space(
vertex_perspective_divide(
vertex_rotate(cube_vertex_position[ic])));
uint32_t va_color = cube_vertex_color[ia];
uint32_t vb_color = cube_vertex_color[ib];
uint32_t vc_color = cube_vertex_color[ic];
voodoo2->sVx = va.x;
voodoo2->sVy = va.y;
voodoo2->sWb = va.z;
voodoo2->sARGB = va_color;
voodoo2->sBeginTriCMD = 1;
wait_graphics_busy(voodoo2);
voodoo2->sVx = vb.x;
voodoo2->sVy = vb.y;
voodoo2->sWb = vb.z;
voodoo2->sARGB = vb_color;
voodoo2->sDrawTriCMD = 1;
wait_graphics_busy(voodoo2);
voodoo2->sVx = vc.x;
voodoo2->sVy = vc.y;
voodoo2->sWb = vc.z;
voodoo2->sARGB = vc_color;
voodoo2->sDrawTriCMD = 1;
wait_graphics_busy(voodoo2);
}
// swap front/back buffers
voodoo2->swapbufferCMD = 1;
//wait_graphics_busy(voodoo2);
//asdf
while (voodoo2->status & STATUS__SWAP_BUFFERS_PENDING(0x7));
theta += 0.01f;
}
////////////////////////////////////////////////////////////////////////
// cleanup