transfer FP and vertices to VRAM only once; fix vertex array format parameters
[ps3freebsd_ps3gpu_test.git] / util.c
blobbe5fed1ed550e67b0e547940231c257b1cde9aee
1 /*-
2 * Copyright (C) 2011, 2012 glevand <geoffrey.levand@mail.ru>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * $FreeBSD$
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <stdint.h>
32 #include <string.h>
33 #include <math.h>
35 #include <unistd.h>
37 #include "ps3gpu_ctl.h"
38 #include "ps3gpu_mth.h"
39 #include "util.h"
41 int
42 save_image(const char *filename, const char *buf, int len)
44 FILE *fp;
45 int nwritten;
46 int err = 0;
48 fp = fopen(filename, "w");
49 if (!fp)
50 return (-1);
52 nwritten = fwrite(buf, 1, len, fp);
53 if (nwritten != len)
54 err = -1;
56 fclose(fp);
58 return (err);
61 void
62 dump_fifo(FILE *fp, const uint32_t *fifo, unsigned int word_count)
64 int i = 0;
66 while (word_count--) {
67 fprintf(fp, "%08x: %08x\n", i * 4, fifo[i]);
68 i++;
72 int
73 transfer_data(uint32_t *fifo, uint32_t src, uint32_t dst,
74 uint32_t dst_offset, int32_t dst_pitch, uint32_t src_offset, int32_t src_pitch,
75 uint32_t row_length, uint32_t row_count)
77 int h;
78 int i = 0;
80 fifo[i++] = PS3GPU_MTH_HDR(2, 1, 0x184);
81 fifo[i++] = src;
82 fifo[i++] = dst;
84 while (row_count) {
85 h = row_count;
86 if (h > 2047)
87 h = 2047;
89 fifo[i++] = PS3GPU_MTH_HDR(8, 1, 0x30c);
90 fifo[i++] = src_offset;
91 fifo[i++] = dst_offset;
92 fifo[i++] = src_pitch;
93 fifo[i++] = dst_pitch;
94 fifo[i++] = row_length;
95 fifo[i++] = h;
96 fifo[i++] = 0x00000101;
97 fifo[i++] = 0x00000000;
99 src_offset += h * src_pitch;
100 dst_offset += h * dst_pitch;
101 row_count -= h;
104 fifo[i++] = PS3GPU_MTH_HDR(1, 1, 0x310);
105 fifo[i++] = 0x00000000;
107 return (i);
111 transfer_inline(uint32_t *fifo, uint32_t dst, uint32_t dst_offset,
112 const uint32_t *data, uint32_t word_count)
114 int odd = word_count & 1;
115 int i = 0;
117 fifo[i++] = PS3GPU_MTH_HDR(1, 3, 0x188);
118 fifo[i++] = dst;
120 fifo[i++] = PS3GPU_MTH_HDR(1, 3, 0x30c);
121 fifo[i++] = dst_offset & ~0x3f;
123 fifo[i++] = PS3GPU_MTH_HDR(2, 3, 0x300);
124 fifo[i++] = 0x0000000b;
125 fifo[i++] = 0x10001000;
127 fifo[i++] = PS3GPU_MTH_HDR(3, 5, 0x304);
128 fifo[i++] = (dst_offset >> 2) & 0xf;
129 fifo[i++] = 0x00010000 | word_count;
130 fifo[i++] = 0x00010000 | word_count;
132 fifo[i++] = PS3GPU_MTH_HDR((word_count + 1) & ~1, 5, 0x400);
134 while (word_count--)
135 fifo[i++] = *data++;
137 if (odd)
138 fifo[i++] = 0x00000000;
140 return (i);
144 flip_display_buffer(uint32_t *fifo, uint8_t channel_id, uint8_t buffer_id,
145 uint8_t head)
147 int i = 0;
149 /* reset flip label */
151 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x64);
152 fifo[i++]= (head << 4);
154 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x6c);
155 fifo[i++] = 0x00000001;
157 /* 0xcafebabe flip method */
159 fifo[i++] = PS3GPU_MTH_HDR(1, 7, 0x920 + (head << 2));
160 fifo[i++] = 0x80000000 | (channel_id << 8) | buffer_id;
162 return (i);
166 set_depth_mask(uint32_t *fifo, uint32_t mask)
168 int i = 0;
170 fifo[i++] = PS3GPU_MTH_HDR(1, 0, PS3GPU_MTH_ADDR_DEPTH_MASK);
171 fifo[i++] = mask;
173 return (i);
177 set_color_mask(uint32_t *fifo, uint32_t mask)
179 int i = 0;
181 fifo[i++] = PS3GPU_MTH_HDR(1, 0, PS3GPU_MTH_ADDR_COLOR_MASK);
182 fifo[i++] = mask;
184 return (i);
188 set_color_mask_mrt(uint32_t *fifo, uint32_t mask)
190 int i = 0;
192 fifo[i++] = PS3GPU_MTH_HDR(1, 0, PS3GPU_MTH_ADDR_COLOR_MASK_MRT);
193 fifo[i++] = mask;
195 return (i);
199 set_clear_color(uint32_t *fifo, uint32_t color)
201 int i = 0;
203 fifo[i++] = PS3GPU_MTH_HDR(1, 0, PS3GPU_MTH_ADDR_CLEAR_COLOR);
204 fifo[i++] = color;
206 return (i);
210 set_scissor(uint32_t *fifo, uint16_t x, uint16_t y, uint16_t w, uint16_t h)
212 int i = 0;
214 fifo[i++] = PS3GPU_MTH_HDR(2, 0, PS3GPU_MTH_ADDR_SCISSOR);
215 fifo[i++] = (w << 16) | x;
216 fifo[i++] = (h << 16) | y;
218 return (i);
222 set_front_poly_mode(uint32_t *fifo, uint32_t mode)
224 int i = 0;
226 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x1828);
227 fifo[i++] = mode;
229 return (i);
233 set_shade_mode(uint32_t *fifo, uint32_t mode)
235 int i = 0;
237 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x368);
238 fifo[i++] = mode;
240 return (i);
244 clear_surface(uint32_t *fifo, uint32_t mask)
246 int i = 0;
248 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x1d94);
249 fifo[i++] = mask;
251 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x100);
252 fifo[i++] = 0x00000000;
254 return (i);
258 set_surface(uint32_t *fifo, const struct surface_desc *sd)
260 int i = 0;
262 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x194);
263 fifo[i++] = sd->sd_color_loc[0];
265 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x18c);
266 fifo[i++] = sd->sd_color_loc[1];
268 fifo[i++] = PS3GPU_MTH_HDR(2, 0, 0x1b4);
269 fifo[i++] = sd->sd_color_loc[2];
270 fifo[i++] = sd->sd_color_loc[3];
272 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x198);
273 fifo[i++] = sd->sd_depth_loc;
275 fifo[i++] = PS3GPU_MTH_HDR(6, 0, 0x208);
276 fifo[i++] = ((uint8_t) log2(sd->sd_h) << 24) | ((uint8_t) log2(sd->sd_w) << 16) |
277 (0x0 << 12) | (0x1 << 8) |
278 (sd->sd_depth_fmt << 5) | sd->sd_color_fmt;
279 fifo[i++] = sd->sd_color_pitch[0];
280 fifo[i++] = sd->sd_color_off[0];
281 fifo[i++] = sd->sd_depth_off;
282 fifo[i++] = sd->sd_color_off[1];
283 fifo[i++] = sd->sd_color_pitch[1];
285 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x22c);
286 fifo[i++] = sd->sd_depth_pitch;
288 fifo[i++] = PS3GPU_MTH_HDR(4, 0, 0x280);
289 fifo[i++] = sd->sd_color_pitch[2];
290 fifo[i++] = sd->sd_color_pitch[3];
291 fifo[i++] = sd->sd_color_off[2];
292 fifo[i++] = sd->sd_color_off[3];
294 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x220);
295 fifo[i++] = sd->sd_color_target;
297 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x2b8);
298 fifo[i++] = (sd->sd_y << 16) | sd->sd_x;
300 fifo[i++] = PS3GPU_MTH_HDR(2, 0, 0x200);
301 fifo[i++] = (sd->sd_w << 16) | sd->sd_x;
302 fifo[i++] = (sd->sd_h << 16) | sd->sd_y;
304 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x1d88);
305 fifo[i++] = (0x0 << 16) | (0x1 << 12) |
306 (sd->sd_h - ((sd->sd_h >> 12) & 0x1));
308 return (i);
312 wait_label(uint32_t *fifo, uint32_t index, uint32_t val)
314 int i = 0;
316 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x64);
317 fifo[i++] = index << 4;
319 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x68);
320 fifo[i++] = val;
322 return (i);
326 set_label(uint32_t *fifo, uint32_t index, uint32_t val)
328 int i = 0;
330 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x64);
331 fifo[i++] = index << 4;
333 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x6c);
334 fifo[i++] = val;
336 return (i);
340 set_viewport(uint32_t *fifo, uint16_t x, uint16_t y, uint16_t w, uint16_t h,
341 float zmin, float zmax, const float offset[4], const float scale[4])
343 int i = 0;
345 fifo[i++] = PS3GPU_MTH_HDR(2, 0, 0xa00);
346 fifo[i++] = (w << 16) | x;
347 fifo[i++] = (h << 16) | y;
349 fifo[i++] = PS3GPU_MTH_HDR(2, 0, 0x394);
350 fifo[i++] = *(uint32_t *) &zmin;
351 fifo[i++] = *(uint32_t *) &zmax;
353 fifo[i++] = PS3GPU_MTH_HDR(8, 0, 0xa20);
354 fifo[i++] = *(uint32_t *) &offset[0];
355 fifo[i++] = *(uint32_t *) &offset[1];
356 fifo[i++] = *(uint32_t *) &offset[2];
357 fifo[i++] = *(uint32_t *) &offset[3];
358 fifo[i++] = *(uint32_t *) &scale[0];
359 fifo[i++] = *(uint32_t *) &scale[1];
360 fifo[i++] = *(uint32_t *) &scale[2];
361 fifo[i++] = *(uint32_t *) &scale[3];
363 fifo[i++] = PS3GPU_MTH_HDR(8, 0, 0xa20);
364 fifo[i++] = *(uint32_t *) &offset[0];
365 fifo[i++] = *(uint32_t *) &offset[1];
366 fifo[i++] = *(uint32_t *) &offset[2];
367 fifo[i++] = *(uint32_t *) &offset[3];
368 fifo[i++] = *(uint32_t *) &scale[0];
369 fifo[i++] = *(uint32_t *) &scale[1];
370 fifo[i++] = *(uint32_t *) &scale[2];
371 fifo[i++] = *(uint32_t *) &scale[3];
373 return (i);
377 load_vertex_prg(uint32_t *fifo, uint16_t slot, const uint32_t *prg, int instr_count)
379 int i = 0;
380 int j;
382 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x1e9c);
383 fifo[i++] = slot;
385 while (instr_count >= 32) {
386 fifo[i++] = PS3GPU_MTH_HDR(32, 0, 0xb80);
388 for (j = 0; j < 32; j++) {
389 fifo[i++] = *prg++;
390 fifo[i++] = *prg++;
391 fifo[i++] = *prg++;
392 fifo[i++] = *prg++;
395 instr_count -= 32;
398 if (instr_count > 0) {
399 fifo[i++] = PS3GPU_MTH_HDR(instr_count << 2, 0, 0xb80);
401 for (j = 0; j < instr_count; j++) {
402 fifo[i++] = *prg++;
403 fifo[i++] = *prg++;
404 fifo[i++] = *prg++;
405 fifo[i++] = *prg++;
409 return (i);
413 set_vertex_prg_reg_count(uint32_t *fifo, unsigned int count)
415 int i = 0;
416 uint32_t val;
418 val = (count <= 32) ? 0x0020ffff : 0x0030ffff;
420 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x1ef8);
421 fifo[i++] = val;
423 return (i);
427 set_vertex_prg_start_slot(uint32_t *fifo, uint16_t slot)
429 int i = 0;
431 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x1ea0);
432 fifo[i++] = slot;
434 return (i);
438 set_vertex_attr_inmask(uint32_t *fifo, uint32_t mask)
440 int i = 0;
442 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x1ff0);
443 fifo[i++] = mask;
445 return (i);
449 set_vertex_attr_outmask(uint32_t *fifo, uint32_t mask)
451 int i = 0;
453 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x1ff4);
454 fifo[i++] = mask;
456 return (i);
460 set_frag_prg(uint32_t *fifo, uint8_t location, uint32_t offset)
462 int i = 0;
464 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x8e4);
465 fifo[i++] = offset | location;
467 return (i);
471 frag_prg_ctrl(uint32_t *fifo, uint8_t reg_count, uint8_t replace_txp_with_tex,
472 uint8_t pixel_kill, uint8_t output_from_h0, uint8_t depth_replace)
474 int i = 0;
476 if (reg_count <= 1)
477 reg_count = 2;
479 if (depth_replace)
480 depth_replace = 0x7;
482 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x1d60);
483 fifo[i++] = (reg_count << 24) | (replace_txp_with_tex << 15) | 0x00000400 |
484 (pixel_kill << 7) | (!output_from_h0 << 6) | (depth_replace << 1);
486 return (i);
490 draw_begin(uint32_t *fifo, uint32_t mode)
492 int i = 0;
494 fifo[i++] = 0x40000000 | PS3GPU_MTH_HDR(3, 0, 0x1714);
495 fifo[i++] = 0x00000000;
496 fifo[i++] = 0x00000000;
497 fifo[i++] = 0x00000000;
499 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x1808);
500 fifo[i++] = mode;
502 return (i);
506 draw_end(uint32_t *fifo)
508 int i = 0;
510 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x1808);
511 fifo[i++] = 0x00000000;
513 return (i);
517 set_vertex_data_arrfmt(uint32_t *fifo, uint8_t reg, uint16_t freq,
518 uint8_t stride, uint8_t size, uint8_t type)
520 int i = 0;
522 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x1740 + (reg << 4));
523 fifo[i++] = (freq << 16) | (stride << 8) | (size << 4) | type;
525 return (i);
529 set_vertex_data_4f(uint32_t *fifo, uint8_t reg, const float val[4])
531 int i = 0;
533 fifo[i++] = PS3GPU_MTH_HDR(4, 0, 0x1c00 + (reg << 4));
534 fifo[i++] = *(uint32_t *) &val[0];
535 fifo[i++] = *(uint32_t *) &val[1];
536 fifo[i++] = *(uint32_t *) &val[2];
537 fifo[i++] = *(uint32_t *) &val[3];
539 return (i);
543 set_vertex_data_arr(uint32_t *fifo, uint8_t reg,
544 uint16_t freq, uint8_t stride, uint8_t size, uint8_t type,
545 uint8_t location, uint32_t offset)
547 int i = 0;
549 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x1740 + (reg << 2));
550 fifo[i++] = (freq << 16) | (stride << 8) | (size << 4) | type;
552 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x1680 + (reg << 2));
553 fifo[i++] = (location << 31) | offset;
555 return (i);
559 draw_arrays(uint32_t *fifo, uint32_t mode, uint32_t first, uint32_t count)
561 int i = 0;
562 int j;
564 /* draw begin */
566 fifo[i++] = 0x40000000 | PS3GPU_MTH_HDR(3, 0, 0x1714);
567 fifo[i++] = 0x00000000;
568 fifo[i++] = 0x00000000;
569 fifo[i++] = 0x00000000;
571 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x1808);
572 fifo[i++] = mode;
574 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x1814);
575 fifo[i++] = (((count - 1) & 0xff) << 24) | first;
577 first += ((count - 1) & 0xff) + 1;
578 count -= ((count - 1) & 0xff) + 1;
580 while (count >= (0x7ff * 0x100)) {
581 fifo[i++] = 0x40000000 | PS3GPU_MTH_HDR(0x7ff, 0, 0x1814);
583 for (j = 0; j < 0x7ff; j++) {
584 fifo[i++] = ((0x100 - 1) << 24) | first;
585 first += 0x100;
588 count -= 0x7ff * 0x100;
591 if (count) {
592 fifo[i++] = 0x40000000 | PS3GPU_MTH_HDR(count, 0, 0x1814);
594 for (j = 0; j < count; j++) {
595 fifo[i++] = ((0x100 - 1) << 24) | first;
596 first += 0x100;
600 /* draw end */
602 fifo[i++] = PS3GPU_MTH_HDR(1, 0, 0x1808);
603 fifo[i++] = 0x00000000;
605 return (i);