Subversion Repositories ps3ware

Rev

Rev 189 | Rev 201 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
111 ironpeter 1
/*
2
 * PS3 GPU blitting test program
3
 *
4
 * Copyright 2007 Vivien Chappelier <vivien.chappelier@free.fr>
5
 * Copyright 2007 Peter Popov <IronSPeter@gmail.com>
6
 *
7
 */
8
#include <stdlib.h>
9
#include <stdio.h>
10
#include <stdint.h>
11
#include <unistd.h>
12
#include <string.h>
13
#include <sys/mman.h>
14
#include <sys/ioctl.h>
15
#include <signal.h>
16
#include <fcntl.h>
189 glaurung 17
#include <errno.h>
111 ironpeter 18
 
19
#include <linux/types.h>
20
#include <linux/fb.h>
21
#include <asm/ps3fb.h>
22
#include "utils.h"
189 glaurung 23
#include "ioctl.h"
111 ironpeter 24
 
184 ironpeter 25
#include "../../src/types.h"
26
#include "../../include/nouveau_class.h"
27
 
28
 
29
int setup_and_voodoo
30
(
31
    uint32_t dma_notifier,
32
    uint32_t dma_fb,
33
    uint32_t obj_3d,
34
    uint32_t *fifo,
35
    uint32_t hw_sub
36
)
37
{
38
        uint32_t i;
39
        uint32_t *ptr = fifo;
40
        uint32_t Nv3D = hw_sub;
41
 
42
        BEGIN_RING(Nv3D, 0, 1);
43
        OUT_RING  (obj_3d);
44
 
45
        BEGIN_RING(Nv3D, NV40TCL_DMA_NOTIFY, 1);
46
        OUT_RING  (dma_notifier);
47
        BEGIN_RING(Nv3D, NV40TCL_DMA_TEXTURE0, 1);
48
        OUT_RING  (dma_fb);
49
 
50
        BEGIN_RING(Nv3D, NV40TCL_DMA_COLOR0, 2);
51
        OUT_RING  (dma_fb);
52
        OUT_RING  (dma_fb);
53
 
54
        BEGIN_RING(Nv3D, NV40TCL_DMA_ZETA, 1 );
55
        OUT_RING  (dma_fb);
56
 
57
 
58
        /* voodoo */
59
        BEGIN_RING(Nv3D, 0x1ea4, 3);
60
        OUT_RING  (0x00000010);
61
        OUT_RING  (0x01000100);
62
        OUT_RING  (0xff800006);
63
        BEGIN_RING(Nv3D, 0x1fc4, 1);
64
        OUT_RING  (0x06144321);
65
        BEGIN_RING(Nv3D, 0x1fc8, 2);
66
        OUT_RING  (0xedcba987);
67
        OUT_RING  (0x00000021);
68
        BEGIN_RING(Nv3D, 0x1fd0, 1);
69
        OUT_RING  (0x00171615);
70
        BEGIN_RING(Nv3D, 0x1fd4, 1);
71
        OUT_RING  (0x001b1a19);
72
        BEGIN_RING(Nv3D, 0x1ef8, 1);
73
        OUT_RING  (0x0020ffff);
74
        BEGIN_RING(Nv3D, 0x1d64, 1);
75
        OUT_RING  (0x00d30000);
76
        BEGIN_RING(Nv3D, 0x1e94, 1);
77
        OUT_RING  (0x00000001);
78
 
79
 
80
        /* default 3D state */
81
        BEGIN_RING(Nv3D, NV40TCL_STENCIL_FRONT_ENABLE, 1);
82
        OUT_RING  (0);
83
        BEGIN_RING(Nv3D, NV40TCL_STENCIL_BACK_ENABLE, 1);
84
        OUT_RING  (0);
85
        BEGIN_RING(Nv3D, NV40TCL_ALPHA_TEST_ENABLE, 1);
197 ironpeter 86
        OUT_RING  (1);
87
 
88
        BEGIN_RING(Nv3D, NV40TCL_ALPHA_TEST_FUNC, 1);
89
        OUT_RING  (NV40TCL_ALPHA_TEST_FUNC_GREATER);
90
 
91
        BEGIN_RING(Nv3D, NV40TCL_ALPHA_TEST_REF, 1);
92
        OUT_RING  (0x128);
93
 
94
 
184 ironpeter 95
        BEGIN_RING(Nv3D, NV40TCL_DEPTH_WRITE_ENABLE, 1);
96
        OUT_RING  (1);
97
        BEGIN_RING(Nv3D, NV40TCL_DEPTH_TEST_ENABLE, 1);
98
        OUT_RING  (1);
99
        BEGIN_RING(Nv3D, NV40TCL_DEPTH_FUNC, 1);
100
        OUT_RING  (NV40TCL_DEPTH_FUNC_LESS);
101
        BEGIN_RING(Nv3D, NV40TCL_COLOR_MASK, 1);
102
        OUT_RING  (0x01010101); /* TR,TR,TR,TR */
103
        BEGIN_RING(Nv3D, NV40TCL_CULL_FACE_ENABLE, 1);
104
        OUT_RING  (0);
105
        BEGIN_RING(Nv3D, NV40TCL_BLEND_ENABLE, 1);
106
        OUT_RING  (0);
107
        BEGIN_RING(Nv3D, NV40TCL_COLOR_LOGIC_OP_ENABLE, 2);
108
        OUT_RING  (0);
109
        OUT_RING  (NV40TCL_COLOR_LOGIC_OP_COPY);
110
        BEGIN_RING(Nv3D, NV40TCL_DITHER_ENABLE, 1);
111
        OUT_RING  (0);
112
        BEGIN_RING(Nv3D, NV40TCL_SHADE_MODEL, 1);
113
        OUT_RING  (NV40TCL_SHADE_MODEL_SMOOTH);
114
        BEGIN_RING(Nv3D, NV40TCL_POLYGON_OFFSET_FACTOR,2);
115
        OUT_RINGf (0.0);
116
        OUT_RINGf (0.0);
117
        BEGIN_RING(Nv3D, NV40TCL_POLYGON_MODE_FRONT, 2);
118
        OUT_RING  (NV40TCL_POLYGON_MODE_FRONT_FILL);
119
        OUT_RING  (NV40TCL_POLYGON_MODE_BACK_FILL);
120
        BEGIN_RING(Nv3D, NV40TCL_POLYGON_STIPPLE_PATTERN(0), 0x20);
121
        for (i=0;i<0x20;i++)
122
                OUT_RING  (0xFFFFFFFF);
123
        for (i=0;i<16;i++)
124
        {
125
                BEGIN_RING(Nv3D, NV40TCL_TEX_ENABLE(i), 1);
126
                OUT_RING  (0);
127
        }
128
 
129
        BEGIN_RING(Nv3D, 0x1d78, 1);
130
        OUT_RING  (0x110);
131
        return ptr - fifo;
132
}
133
 
134
int setup_buffers(
135
    const setup_buffer_t *buffers,
136
    uint32_t *fifo,
137
    uint32_t hw_sub )
138
{
139
 
140
        uint32_t *ptr = fifo;
141
        uint32_t Nv3D = hw_sub;
142
        uint16_t width = buffers->width;
143
        uint16_t height = buffers->height;
144
 
145
        printf( "width = %d height = %d \n", (uint32_t)width, (uint32_t)height );
146
 
147
        BEGIN_RING(Nv3D, NV40TCL_VIEWPORT_TRANSLATE_X, 8);
148
        OUT_RINGf (0.5f * width );
149
        OUT_RINGf (0.5f * height );
150
        OUT_RINGf (0.0);
151
        OUT_RINGf (0.0);
152
        OUT_RINGf (0.5f * width );
153
        OUT_RINGf (0.5f * height );
154
        OUT_RINGf (1.0);
155
        OUT_RINGf (1.0);
156
 
157
        BEGIN_RING(Nv3D, NV40TCL_RT_ENABLE, 1);
158
        OUT_RING  (NV40TCL_RT_ENABLE_COLOR0);
159
 
160
        BEGIN_RING(Nv3D, NV40TCL_RT_HORIZ, 2);
161
        OUT_RING  ((width << 16));
162
        OUT_RING  ((height << 16));
163
        BEGIN_RING(Nv3D, NV40TCL_SCISSOR_HORIZ, 2);
164
        OUT_RING  ((width << 16));
165
        OUT_RING  ((height << 16));
166
        BEGIN_RING(Nv3D, NV40TCL_VIEWPORT_HORIZ, 2);
167
        OUT_RING  ((width << 16));
168
        OUT_RING  ((height << 16));
169
        BEGIN_RING(Nv3D, NV40TCL_VIEWPORT_CLIP_HORIZ(0), 2);
170
        OUT_RING  ((width << 16));
171
        OUT_RING  ((height << 16));
172
 
173
 
174
        BEGIN_RING(Nv3D, NV40TCL_ZETA_OFFSET, 1 );
175
        OUT_RING( buffers->offsetDepth );
176
        BEGIN_RING(Nv3D, NV40TCL_ZETA_PITCH, 1 );
177
        OUT_RING( buffers->pitchDepth );
178
 
179
 
180
 
181
        BEGIN_RING(Nv3D, NV40TCL_RT_FORMAT, 3);
182
        OUT_RING  (NV40TCL_RT_FORMAT_TYPE_LINEAR |
183
                   buffers->typeDepth |
184
                   NV40TCL_RT_FORMAT_COLOR_A8R8G8B8);
185
        OUT_RING  ( buffers->pitchColor );
186
        OUT_RING  ( buffers->offsetColor );
187
 
188
        return ptr - fifo;
189
}
190
 
191
int clear_buffers(
192
    const clear_buffer_t *buffers,
193
    uint32_t *fifo,
194
    uint32_t hw_sub )
195
{
196
        uint32_t *ptr = fifo;
197
        uint32_t Nv3D = hw_sub;
198
 
199
        BEGIN_RING(Nv3D, NV40TCL_CLEAR_VALUE_COLOR, 1 );
200
        OUT_RING( buffers->rgba );
201
 
202
        BEGIN_RING(Nv3D, NV40TCL_CLEAR_VALUE_DEPTH, 1 );
203
        OUT_RING( buffers->depth );
204
 
205
 
206
        BEGIN_RING(Nv3D,NV40TCL_CLEAR_BUFFERS,1 );
207
        OUT_RING
208
        (
209
            ( buffers->clearB ? NV40TCL_CLEAR_BUFFERS_COLOR_B : 0 ) |
210
            ( buffers->clearG ? NV40TCL_CLEAR_BUFFERS_COLOR_G : 0 ) |
211
            ( buffers->clearR ? NV40TCL_CLEAR_BUFFERS_COLOR_R : 0 ) |
212
            ( buffers->clearA ? NV40TCL_CLEAR_BUFFERS_COLOR_A : 0 ) |
213
            ( buffers->clearD ? NV40TCL_CLEAR_BUFFERS_STENCIL : 0 ) |
214
            ( buffers->clearD ? NV40TCL_CLEAR_BUFFERS_DEPTH : 0 )
215
        );
216
 
217
        return ptr - fifo;
218
}
219
 
220
 
111 ironpeter 221
uint32_t endian( uint32_t v )
222
{
184 ironpeter 223
        return ( ( ( v >> 24 ) & 0xff ) << 0 ) |
224
               ( ( ( v >> 16 ) & 0xff ) << 8 ) |
225
               ( ( ( v >> 8 ) & 0xff ) << 16 ) |
226
               ( ( ( v >> 0 ) & 0xff ) << 24 );
111 ironpeter 227
}
228
 
229
uint32_t endian_fp( uint32_t v )
230
{
184 ironpeter 231
        return ( ( ( v >> 16 ) & 0xffff ) << 0 ) |
232
               ( ( ( v >> 0 ) & 0xffff ) << 16 );
111 ironpeter 233
 
234
}
235
 
189 glaurung 236
static int map_resource(int fd, off_t offset, struct resource *res)
111 ironpeter 237
{
184 ironpeter 238
        void *virt;
111 ironpeter 239
 
189 glaurung 240
        virt = mmap(0, res->len, PROT_READ | PROT_WRITE,
241
                    MAP_SHARED, fd, offset);
111 ironpeter 242
 
184 ironpeter 243
        if (virt == MAP_FAILED)
244
                return -1;
111 ironpeter 245
 
184 ironpeter 246
        res->virt = virt;
111 ironpeter 247
 
184 ironpeter 248
        return 0;
111 ironpeter 249
}
250
 
251
int unmap_resource(struct resource *res)
252
{
184 ironpeter 253
        munmap(res->virt, res->len);
254
        res->virt = NULL;
111 ironpeter 255
 
184 ironpeter 256
        return 0;
111 ironpeter 257
}
258
 
189 glaurung 259
int unmap_gpu(struct gpu *gpu)
111 ironpeter 260
{
189 glaurung 261
        unmap_resource(&gpu->ctrl);
184 ironpeter 262
        unmap_resource(&gpu->fifo);
263
        unmap_resource(&gpu->vram);
111 ironpeter 264
 
184 ironpeter 265
        return 0;
111 ironpeter 266
}
267
 
268
void fifo_push(struct gpu *gpu, int len)
269
{
184 ironpeter 270
        uint32_t *ctrl = gpu->ctrl.virt;
111 ironpeter 271
 
184 ironpeter 272
        ctrl[0x10] += 4 * len;
111 ironpeter 273
}
274
 
275
void fifo_wait(struct gpu *gpu)
276
{
184 ironpeter 277
        volatile uint32_t *ctrl = gpu->ctrl.virt;
111 ironpeter 278
 
184 ironpeter 279
        while (ctrl[0x10] != ctrl[0x11]);
111 ironpeter 280
}
281
 
189 glaurung 282
#define RAMHT_BITS 11
111 ironpeter 283
 
189 glaurung 284
uint32_t hash_handle(int channel, uint32_t handle)
285
{
286
        uint32_t hash = 0;
287
        int i;
111 ironpeter 288
 
189 glaurung 289
//      printf("ch%d handle=0x%08x\n", channel, handle);
290
 
291
        for (i = 32; i > 0; i -= RAMHT_BITS) {
292
                hash ^= (handle & ((1 << RAMHT_BITS) - 1));
293
                handle >>= RAMHT_BITS;
294
        }
295
 
296
        hash ^= channel << (RAMHT_BITS - 4);
297
        hash <<= 3;
111 ironpeter 298
 
189 glaurung 299
//      printf("hash = %08x\n", hash);
300
 
301
        return hash;
302
}
303
 
197 ironpeter 304
int sync_gpu(struct gpu *gpu)
305
{
306
    int val;
307
    ioctl(gpu->fb_fd, FBIO_WAITFORVSYNC, &val);
308
    return val;
309
}
310
 
311
 
189 glaurung 312
int gpu_init(struct gpu *gpu)
111 ironpeter 313
{
189 glaurung 314
        struct ps3rsx_ioctl_context_info info;
184 ironpeter 315
        int ret = 0;
189 glaurung 316
        int fb_fd, rsx_fd;
184 ironpeter 317
        int val = 0;
111 ironpeter 318
 
189 glaurung 319
        memset(gpu, 0, sizeof(gpu));
320
 
321
        if ((fb_fd = open(DEV_VFB, O_RDWR)) < 0)
184 ironpeter 322
        {
323
                perror("open");
324
                return -1;
325
        }
111 ironpeter 326
 
189 glaurung 327
        /* get the screen res info */
328
        if ((ret = ioctl(fb_fd, PS3FB_IOCTL_SCREENINFO, &gpu->res)) < 0)
184 ironpeter 329
        {
330
                perror("ioctl");
189 glaurung 331
                goto err_close_fb;
184 ironpeter 332
        }
111 ironpeter 333
 
184 ironpeter 334
        /* stop that incessant blitting! */
189 glaurung 335
        if ((ret = ioctl(fb_fd, PS3FB_IOCTL_ON, 0)) < 0)
184 ironpeter 336
        {
337
                perror("ioctl");
189 glaurung 338
                goto err_close_fb;
184 ironpeter 339
        }
111 ironpeter 340
 
184 ironpeter 341
        /* wait for vsync */
189 glaurung 342
        if ((ret = ioctl(fb_fd, FBIO_WAITFORVSYNC, &val)) < 0)
184 ironpeter 343
        {
344
                perror("ioctl");
189 glaurung 345
                goto err_leave_direct;
184 ironpeter 346
        }
111 ironpeter 347
 
189 glaurung 348
        /* open gpu */
349
        if ((ret = open(DEV_RSX, O_RDWR)) < 0)
184 ironpeter 350
        {
189 glaurung 351
                fprintf(stderr, "failed to open RSX device: %s\n", strerror(errno));
352
                goto err_leave_direct;
353
        }
354
 
355
        rsx_fd = ret;
356
 
357
        /* get context info */
358
        if ((ret = ioctl(rsx_fd, PS3RSX_IOCTL_CONTEXT_INFO, &info)) < 0)
359
        {
184 ironpeter 360
                perror("ioctl");
189 glaurung 361
                goto err_close_rsx;
184 ironpeter 362
        }
111 ironpeter 363
 
189 glaurung 364
/*
365
        printf("id %d, ioif %d at 0x%08x, vram %d, fifo %d, ctrl %d, reports %d\n",
366
               info.hw_id, info.ioif_size, info.ioif_addr,
367
               info.vram_size, info.fifo_size, info.ctrl_size, info.reports_size);
368
*/
111 ironpeter 369
 
189 glaurung 370
        gpu->hw_id = info.hw_id;
371
        gpu->ioif  = info.ioif_addr;
372
        gpu->xram.len = info.ioif_size;
373
        gpu->vram.len = info.vram_size;
374
        gpu->fifo.len = info.fifo_size;
375
        gpu->ctrl.len = info.ctrl_size;
376
        gpu->reports.len = info.reports_size;
111 ironpeter 377
 
189 glaurung 378
        /* map XDR apperture */
379
        if ((ret = map_resource(rsx_fd, OFFSET_IOIF, &gpu->xram)) < 0)
380
        {
381
                fprintf(stderr, "failed to map vram\n");
382
                goto err_close_rsx;
383
        }
111 ironpeter 384
 
189 glaurung 385
        /* map video RAM */
386
        if ((ret = map_resource(rsx_fd, OFFSET_VRAM, &gpu->vram)) < 0)
387
        {
388
                fprintf(stderr, "failed to map vram\n");
389
                goto err_unmap_ioif;
390
        }
111 ironpeter 391
 
189 glaurung 392
        /* map FIFO */
393
        if ((ret = map_resource(rsx_fd, OFFSET_FIFO, &gpu->fifo)) < 0)
184 ironpeter 394
        {
189 glaurung 395
                fprintf(stderr, "failed to map fifo\n");
396
                goto err_unmap_vram;
397
        }
398
 
399
        /* map FIFO control registers */
400
        if ((ret = map_resource(rsx_fd, OFFSET_CTRL, &gpu->ctrl)) < 0)
401
        {
402
                fprintf(stderr, "failed to map ctrl\n");
403
                goto err_unmap_fifo;
404
        }
405
 
406
        /* map DMA notify region */
407
        if ((ret = map_resource(rsx_fd, OFFSET_REPORTS, &gpu->reports)) < 0)
408
        {
409
                fprintf(stderr, "failed to map ctrl\n");
410
                goto err_unmap_ctrl;
411
        }
412
 
413
        /* enter exclusive mode */
414
        if ((ret = ioctl(rsx_fd, PS3RSX_IOCTL_EXCLUSIVE, NULL)) < 0)
415
        {
184 ironpeter 416
                perror("ioctl");
189 glaurung 417
                goto err_unmap_reports;
184 ironpeter 418
        }
111 ironpeter 419
 
189 glaurung 420
        gpu->fb_fd = fb_fd;
421
        gpu->rsx_fd = rsx_fd;
422
        gpu->init = 1;
111 ironpeter 423
 
189 glaurung 424
        return 0;
425
 
426
err_unmap_reports:
427
        unmap_resource(&gpu->reports);
428
err_unmap_ctrl:
429
        unmap_resource(&gpu->ctrl);
430
err_unmap_fifo:
431
        unmap_resource(&gpu->fifo);
432
err_unmap_vram:
433
        unmap_resource(&gpu->vram);
434
err_unmap_ioif:
435
        unmap_resource(&gpu->xram);
436
err_close_rsx:
437
        close(rsx_fd);
438
err_leave_direct:
439
        ioctl(fb_fd, PS3FB_IOCTL_OFF, 0);
440
err_close_fb:
441
        close(fb_fd);
442
 
184 ironpeter 443
        return ret;
111 ironpeter 444
}
445
 
189 glaurung 446
void gpu_cleanup(struct gpu *gpu)
447
{
448
        int rsx_fd, fb_fd;
449
 
450
        fb_fd = gpu->fb_fd;
451
        rsx_fd = gpu->rsx_fd;
452
 
453
        unmap_resource(&gpu->reports);
454
        unmap_resource(&gpu->ctrl);
455
        unmap_resource(&gpu->fifo);
456
        unmap_resource(&gpu->vram);
457
        unmap_resource(&gpu->xram);
458
        close(rsx_fd);
459
        ioctl(fb_fd, PS3FB_IOCTL_OFF, 0);
460
        close(fb_fd);
461
 
462
        gpu->init = 0;
463
}