103b705cfSriastradh/* 203b705cfSriastradh * Copyright © 2007-2011 Intel Corporation 303b705cfSriastradh * 403b705cfSriastradh * Permission is hereby granted, free of charge, to any person obtaining a 503b705cfSriastradh * copy of this software and associated documentation files (the "Software"), 603b705cfSriastradh * to deal in the Software without restriction, including without limitation 703b705cfSriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense, 803b705cfSriastradh * and/or sell copies of the Software, and to permit persons to whom the 903b705cfSriastradh * Software is furnished to do so, subject to the following conditions: 1003b705cfSriastradh * 1103b705cfSriastradh * The above copyright notice and this permission notice (including the next 1203b705cfSriastradh * paragraph) shall be included in all copies or substantial portions of the 1303b705cfSriastradh * Software. 1403b705cfSriastradh * 1503b705cfSriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1603b705cfSriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1703b705cfSriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1803b705cfSriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1903b705cfSriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2003b705cfSriastradh * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2103b705cfSriastradh * SOFTWARE. 2203b705cfSriastradh * 2303b705cfSriastradh * Authors: 2403b705cfSriastradh * Eric Anholt <eric@anholt.net> 2503b705cfSriastradh * Chris Wilson <chris@chris-wilson.co.uk> 2603b705cfSriastradh * 2703b705cfSriastradh */ 2803b705cfSriastradh 2903b705cfSriastradh#ifdef HAVE_CONFIG_H 3003b705cfSriastradh#include "config.h" 3103b705cfSriastradh#endif 3203b705cfSriastradh 3303b705cfSriastradh#include <sys/mman.h> 3403b705cfSriastradh#include <assert.h> 3503b705cfSriastradh 3603b705cfSriastradh#include "sna.h" 3703b705cfSriastradh 3803b705cfSriastradh#include "gen2_render.h" 3903b705cfSriastradh 4003b705cfSriastradh#include "kgem_debug.h" 4103b705cfSriastradh 4203b705cfSriastradhstatic struct state { 4303b705cfSriastradh int vertex_format; 4403b705cfSriastradh} state; 4503b705cfSriastradh 4603b705cfSriastradhstatic inline float int_as_float(uint32_t dw) 4703b705cfSriastradh{ 4803b705cfSriastradh union { 4903b705cfSriastradh float f; 5003b705cfSriastradh uint32_t dw; 5103b705cfSriastradh } u; 5203b705cfSriastradh u.dw = dw; 5303b705cfSriastradh return u.f; 5403b705cfSriastradh} 5503b705cfSriastradh 5603b705cfSriastradhstatic int 5703b705cfSriastradhdecode_3d_primitive(struct kgem *kgem, uint32_t offset) 5803b705cfSriastradh{ 5903b705cfSriastradh uint32_t *data = kgem->batch + offset; 6003b705cfSriastradh char immediate = (data[0] & (1 << 23)) == 0; 6103b705cfSriastradh unsigned int len; 6203b705cfSriastradh const char *primtype; 6303b705cfSriastradh 6403b705cfSriastradh switch ((data[0] >> 18) & 0xf) { 6503b705cfSriastradh case 0x0: primtype = "TRILIST"; break; 6603b705cfSriastradh case 0x1: primtype = "TRISTRIP"; break; 6703b705cfSriastradh case 0x2: primtype = "TRISTRIP_REVERSE"; break; 6803b705cfSriastradh case 0x3: primtype = "TRIFAN"; break; 6903b705cfSriastradh case 0x4: primtype = "POLYGON"; break; 7003b705cfSriastradh case 0x5: primtype = "LINELIST"; break; 7103b705cfSriastradh case 0x6: primtype = "LINESTRIP"; break; 7203b705cfSriastradh case 0x7: primtype = "RECTLIST"; break; 7303b705cfSriastradh case 0x8: primtype = "POINTLIST"; break; 7403b705cfSriastradh case 0x9: primtype = "DIB"; break; 7503b705cfSriastradh case 0xa: primtype = "CLEAR_RECT"; break; 7603b705cfSriastradh default: primtype = "unknown"; break; 7703b705cfSriastradh } 7803b705cfSriastradh 7903b705cfSriastradh /* XXX: 3DPRIM_DIB not supported */ 8003b705cfSriastradh if (immediate) { 8103b705cfSriastradh len = (data[0] & 0x0003ffff) + 2; 8203b705cfSriastradh kgem_debug_print(data, offset, 0, "3DPRIMITIVE inline %s\n", primtype); 8303b705cfSriastradh#if 0 8403b705cfSriastradh if (!saved_s2_set || !saved_s4_set) { 8503b705cfSriastradh fprintf(out, "unknown vertex format\n"); 8603b705cfSriastradh for (i = 1; i < len; i++) { 8703b705cfSriastradh kgem_debug_print(data, offset, i, 8803b705cfSriastradh " vertex data (%f float)\n", 8903b705cfSriastradh int_as_float(data[i])); 9003b705cfSriastradh } 9103b705cfSriastradh } else { 9203b705cfSriastradh unsigned int vertex = 0; 9303b705cfSriastradh for (i = 1; i < len;) { 9403b705cfSriastradh unsigned int tc; 9503b705cfSriastradh 9603b705cfSriastradh#define VERTEX_OUT(fmt, ...) do { \ 9703b705cfSriastradh if (i < len) \ 9803b705cfSriastradh kgem_debug_print(data, offset, i, " V%d."fmt"\n", vertex, __VA_ARGS__); \ 9903b705cfSriastradh else \ 10003b705cfSriastradh fprintf(out, " missing data in V%d\n", vertex); \ 10103b705cfSriastradh i++; \ 10203b705cfSriastradh} while (0) 10303b705cfSriastradh 10403b705cfSriastradh VERTEX_OUT("X = %f", int_as_float(data[i])); 10503b705cfSriastradh VERTEX_OUT("Y = %f", int_as_float(data[i])); 10603b705cfSriastradh switch (saved_s4 >> 6 & 0x7) { 10703b705cfSriastradh case 0x1: 10803b705cfSriastradh VERTEX_OUT("Z = %f", int_as_float(data[i])); 10903b705cfSriastradh break; 11003b705cfSriastradh case 0x2: 11103b705cfSriastradh VERTEX_OUT("Z = %f", int_as_float(data[i])); 11203b705cfSriastradh VERTEX_OUT("W = %f", int_as_float(data[i])); 11303b705cfSriastradh break; 11403b705cfSriastradh case 0x3: 11503b705cfSriastradh break; 11603b705cfSriastradh case 0x4: 11703b705cfSriastradh VERTEX_OUT("W = %f", int_as_float(data[i])); 11803b705cfSriastradh break; 11903b705cfSriastradh default: 12003b705cfSriastradh fprintf(out, "bad S4 position mask\n"); 12103b705cfSriastradh } 12203b705cfSriastradh 12303b705cfSriastradh if (saved_s4 & (1 << 10)) { 12403b705cfSriastradh VERTEX_OUT("color = (A=0x%02x, R=0x%02x, G=0x%02x, " 12503b705cfSriastradh "B=0x%02x)", 12603b705cfSriastradh data[i] >> 24, 12703b705cfSriastradh (data[i] >> 16) & 0xff, 12803b705cfSriastradh (data[i] >> 8) & 0xff, 12903b705cfSriastradh data[i] & 0xff); 13003b705cfSriastradh } 13103b705cfSriastradh if (saved_s4 & (1 << 11)) { 13203b705cfSriastradh VERTEX_OUT("spec = (A=0x%02x, R=0x%02x, G=0x%02x, " 13303b705cfSriastradh "B=0x%02x)", 13403b705cfSriastradh data[i] >> 24, 13503b705cfSriastradh (data[i] >> 16) & 0xff, 13603b705cfSriastradh (data[i] >> 8) & 0xff, 13703b705cfSriastradh data[i] & 0xff); 13803b705cfSriastradh } 13903b705cfSriastradh if (saved_s4 & (1 << 12)) 14003b705cfSriastradh VERTEX_OUT("width = 0x%08x)", data[i]); 14103b705cfSriastradh 14203b705cfSriastradh for (tc = 0; tc <= 7; tc++) { 14303b705cfSriastradh switch ((saved_s2 >> (tc * 4)) & 0xf) { 14403b705cfSriastradh case 0x0: 14503b705cfSriastradh VERTEX_OUT("T%d.X = %f", tc, int_as_float(data[i])); 14603b705cfSriastradh VERTEX_OUT("T%d.Y = %f", tc, int_as_float(data[i])); 14703b705cfSriastradh break; 14803b705cfSriastradh case 0x1: 14903b705cfSriastradh VERTEX_OUT("T%d.X = %f", tc, int_as_float(data[i])); 15003b705cfSriastradh VERTEX_OUT("T%d.Y = %f", tc, int_as_float(data[i])); 15103b705cfSriastradh VERTEX_OUT("T%d.Z = %f", tc, int_as_float(data[i])); 15203b705cfSriastradh break; 15303b705cfSriastradh case 0x2: 15403b705cfSriastradh VERTEX_OUT("T%d.X = %f", tc, int_as_float(data[i])); 15503b705cfSriastradh VERTEX_OUT("T%d.Y = %f", tc, int_as_float(data[i])); 15603b705cfSriastradh VERTEX_OUT("T%d.Z = %f", tc, int_as_float(data[i])); 15703b705cfSriastradh VERTEX_OUT("T%d.W = %f", tc, int_as_float(data[i])); 15803b705cfSriastradh break; 15903b705cfSriastradh case 0x3: 16003b705cfSriastradh VERTEX_OUT("T%d.X = %f", tc, int_as_float(data[i])); 16103b705cfSriastradh break; 16203b705cfSriastradh case 0x4: 16303b705cfSriastradh VERTEX_OUT("T%d.XY = 0x%08x half-float", tc, data[i]); 16403b705cfSriastradh break; 16503b705cfSriastradh case 0x5: 16603b705cfSriastradh VERTEX_OUT("T%d.XY = 0x%08x half-float", tc, data[i]); 16703b705cfSriastradh VERTEX_OUT("T%d.ZW = 0x%08x half-float", tc, data[i]); 16803b705cfSriastradh break; 16903b705cfSriastradh case 0xf: 17003b705cfSriastradh break; 17103b705cfSriastradh default: 17203b705cfSriastradh fprintf(out, "bad S2.T%d format\n", tc); 17303b705cfSriastradh } 17403b705cfSriastradh } 17503b705cfSriastradh vertex++; 17603b705cfSriastradh } 17703b705cfSriastradh } 17803b705cfSriastradh#endif 17903b705cfSriastradh } else { 18003b705cfSriastradh /* indirect vertices */ 18103b705cfSriastradh len = data[0] & 0x0000ffff; /* index count */ 18203b705cfSriastradh#if 0 18303b705cfSriastradh if (data[0] & (1 << 17)) { 18403b705cfSriastradh /* random vertex access */ 18503b705cfSriastradh kgem_debug_print(data, offset, 0, 18603b705cfSriastradh "3DPRIMITIVE random indirect %s (%d)\n", primtype, len); 18703b705cfSriastradh if (len == 0) { 18803b705cfSriastradh /* vertex indices continue until 0xffff is found */ 18903b705cfSriastradh for (i = 1; i < count; i++) { 19003b705cfSriastradh if ((data[i] & 0xffff) == 0xffff) { 19103b705cfSriastradh kgem_debug_print(data, offset, i, 19203b705cfSriastradh " indices: (terminator)\n"); 19303b705cfSriastradh ret = i; 19403b705cfSriastradh goto out; 19503b705cfSriastradh } else if ((data[i] >> 16) == 0xffff) { 19603b705cfSriastradh kgem_debug_print(data, offset, i, 19703b705cfSriastradh " indices: 0x%04x, (terminator)\n", 19803b705cfSriastradh data[i] & 0xffff); 19903b705cfSriastradh ret = i; 20003b705cfSriastradh goto out; 20103b705cfSriastradh } else { 20203b705cfSriastradh kgem_debug_print(data, offset, i, 20303b705cfSriastradh " indices: 0x%04x, 0x%04x\n", 20403b705cfSriastradh data[i] & 0xffff, data[i] >> 16); 20503b705cfSriastradh } 20603b705cfSriastradh } 20703b705cfSriastradh fprintf(out, 20803b705cfSriastradh "3DPRIMITIVE: no terminator found in index buffer\n"); 20903b705cfSriastradh ret = count; 21003b705cfSriastradh goto out; 21103b705cfSriastradh } else { 21203b705cfSriastradh /* fixed size vertex index buffer */ 21303b705cfSriastradh for (j = 1, i = 0; i < len; i += 2, j++) { 21403b705cfSriastradh if (i * 2 == len - 1) { 21503b705cfSriastradh kgem_debug_print(data, offset, j, 21603b705cfSriastradh " indices: 0x%04x\n", 21703b705cfSriastradh data[j] & 0xffff); 21803b705cfSriastradh } else { 21903b705cfSriastradh kgem_debug_print(data, offset, j, 22003b705cfSriastradh " indices: 0x%04x, 0x%04x\n", 22103b705cfSriastradh data[j] & 0xffff, data[j] >> 16); 22203b705cfSriastradh } 22303b705cfSriastradh } 22403b705cfSriastradh } 22503b705cfSriastradh ret = (len + 1) / 2 + 1; 22603b705cfSriastradh goto out; 22703b705cfSriastradh } else { 22803b705cfSriastradh /* sequential vertex access */ 22903b705cfSriastradh kgem_debug_print(data, offset, 0, 23003b705cfSriastradh "3DPRIMITIVE sequential indirect %s, %d starting from " 23103b705cfSriastradh "%d\n", primtype, len, data[1] & 0xffff); 23203b705cfSriastradh kgem_debug_print(data, offset, 1, " start\n"); 23303b705cfSriastradh ret = 2; 23403b705cfSriastradh goto out; 23503b705cfSriastradh } 23603b705cfSriastradh#endif 23703b705cfSriastradh } 23803b705cfSriastradh 23903b705cfSriastradh return len; 24003b705cfSriastradh} 24103b705cfSriastradh 24203b705cfSriastradhstatic int 24303b705cfSriastradhdecode_3d_1d(struct kgem *kgem, uint32_t offset) 24403b705cfSriastradh{ 24503b705cfSriastradh uint32_t *data = kgem->batch + offset; 24603b705cfSriastradh unsigned int len, i, idx, word, map; 24703b705cfSriastradh const char *format, *zformat, *type; 24803b705cfSriastradh uint32_t opcode; 24903b705cfSriastradh 25003b705cfSriastradh static const struct { 25103b705cfSriastradh uint32_t opcode; 25203b705cfSriastradh int min_len; 25303b705cfSriastradh int max_len; 25403b705cfSriastradh const char *name; 25503b705cfSriastradh } opcodes_3d_1d[] = { 25603b705cfSriastradh { 0x86, 4, 4, "3DSTATE_CHROMA_KEY" }, 25703b705cfSriastradh { 0x88, 2, 2, "3DSTATE_CONSTANT_BLEND_COLOR" }, 25803b705cfSriastradh { 0x99, 2, 2, "3DSTATE_DEFAULT_DIFFUSE" }, 25903b705cfSriastradh { 0x9a, 2, 2, "3DSTATE_DEFAULT_SPECULAR" }, 26003b705cfSriastradh { 0x98, 2, 2, "3DSTATE_DEFAULT_Z" }, 26103b705cfSriastradh { 0x97, 2, 2, "3DSTATE_DEPTH_OFFSET_SCALE" }, 26203b705cfSriastradh { 0x9d, 65, 65, "3DSTATE_FILTER_COEFFICIENTS_4X4" }, 26303b705cfSriastradh { 0x9e, 4, 4, "3DSTATE_MONO_FILTER" }, 26403b705cfSriastradh { 0x89, 4, 4, "3DSTATE_FOG_MODE" }, 26503b705cfSriastradh { 0x8f, 2, 16, "3DSTATE_MAP_PALLETE_LOAD_32" }, 26603b705cfSriastradh { 0x83, 2, 2, "3DSTATE_SPAN_STIPPLE" }, 26703b705cfSriastradh { 0x8c, 2, 2, "3DSTATE_MAP_COORD_TRANSFORM" }, 26803b705cfSriastradh { 0x8b, 2, 2, "3DSTATE_MAP_VERTEX_TRANSFORM" }, 26903b705cfSriastradh { 0x8d, 3, 3, "3DSTATE_W_STATE" }, 27003b705cfSriastradh { 0x01, 2, 2, "3DSTATE_COLOR_FACTOR" }, 27103b705cfSriastradh { 0x02, 2, 2, "3DSTATE_MAP_COORD_SETBIND" }, 27203b705cfSriastradh }, *opcode_3d_1d; 27303b705cfSriastradh 27403b705cfSriastradh opcode = (data[0] & 0x00ff0000) >> 16; 27503b705cfSriastradh 27603b705cfSriastradh switch (opcode) { 27703b705cfSriastradh case 0x07: 27803b705cfSriastradh /* This instruction is unusual. A 0 length means just 1 DWORD instead of 27903b705cfSriastradh * 2. The 0 length is specified in one place to be unsupported, but 28003b705cfSriastradh * stated to be required in another, and 0 length LOAD_INDIRECTs appear 28103b705cfSriastradh * to cause no harm at least. 28203b705cfSriastradh */ 28303b705cfSriastradh kgem_debug_print(data, offset, 0, "3DSTATE_LOAD_INDIRECT\n"); 28403b705cfSriastradh len = (data[0] & 0x000000ff) + 1; 28503b705cfSriastradh i = 1; 28603b705cfSriastradh if (data[0] & (0x01 << 8)) { 28703b705cfSriastradh kgem_debug_print(data, offset, i++, "SIS.0\n"); 28803b705cfSriastradh kgem_debug_print(data, offset, i++, "SIS.1\n"); 28903b705cfSriastradh } 29003b705cfSriastradh if (data[0] & (0x02 << 8)) { 29103b705cfSriastradh kgem_debug_print(data, offset, i++, "DIS.0\n"); 29203b705cfSriastradh } 29303b705cfSriastradh if (data[0] & (0x04 << 8)) { 29403b705cfSriastradh kgem_debug_print(data, offset, i++, "SSB.0\n"); 29503b705cfSriastradh kgem_debug_print(data, offset, i++, "SSB.1\n"); 29603b705cfSriastradh } 29703b705cfSriastradh if (data[0] & (0x08 << 8)) { 29803b705cfSriastradh kgem_debug_print(data, offset, i++, "MSB.0\n"); 29903b705cfSriastradh kgem_debug_print(data, offset, i++, "MSB.1\n"); 30003b705cfSriastradh } 30103b705cfSriastradh if (data[0] & (0x10 << 8)) { 30203b705cfSriastradh kgem_debug_print(data, offset, i++, "PSP.0\n"); 30303b705cfSriastradh kgem_debug_print(data, offset, i++, "PSP.1\n"); 30403b705cfSriastradh } 30503b705cfSriastradh if (data[0] & (0x20 << 8)) { 30603b705cfSriastradh kgem_debug_print(data, offset, i++, "PSC.0\n"); 30703b705cfSriastradh kgem_debug_print(data, offset, i++, "PSC.1\n"); 30803b705cfSriastradh } 30903b705cfSriastradh assert(len == i); 31003b705cfSriastradh return len; 31103b705cfSriastradh case 0x04: 31203b705cfSriastradh kgem_debug_print(data, offset, 0, "3DSTATE_LOAD_STATE_IMMEDIATE_1\n"); 31303b705cfSriastradh len = (data[0] & 0x0000000f) + 2; 31403b705cfSriastradh i = 1; 31503b705cfSriastradh for (word = 0; word <= 8; word++) { 31603b705cfSriastradh if (data[0] & (1 << (4 + word))) { 31703b705cfSriastradh kgem_debug_print(data, offset, i, "S%d: 0x%08x\n", i, data[i]); 31803b705cfSriastradh i++; 31903b705cfSriastradh } 32003b705cfSriastradh } 32103b705cfSriastradh assert (len ==i); 32203b705cfSriastradh return len; 32303b705cfSriastradh case 0x03: 32403b705cfSriastradh kgem_debug_print(data, offset, 0, "3DSTATE_LOAD_STATE_IMMEDIATE_2\n"); 32503b705cfSriastradh len = (data[0] & 0x0000000f) + 2; 32603b705cfSriastradh i = 1; 32703b705cfSriastradh for (word = 6; word <= 14; word++) { 32803b705cfSriastradh if (data[0] & (1 << word)) { 32903b705cfSriastradh if (word == 6) 33003b705cfSriastradh kgem_debug_print(data, offset, i++, "TBCF\n"); 33103b705cfSriastradh else if (word >= 7 && word <= 10) { 33203b705cfSriastradh kgem_debug_print(data, offset, i++, "TB%dC\n", word - 7); 33303b705cfSriastradh kgem_debug_print(data, offset, i++, "TB%dA\n", word - 7); 33403b705cfSriastradh } else if (word >= 11 && word <= 14) { 33503b705cfSriastradh kgem_debug_print(data, offset, i, "TM%dS0: offset=0x%08x, %s\n", 33603b705cfSriastradh word - 11, 33703b705cfSriastradh data[i]&0xfffffffe, 33803b705cfSriastradh data[i]&1?"use fence":""); 33903b705cfSriastradh i++; 34003b705cfSriastradh kgem_debug_print(data, offset, i, "TM%dS1: height=%i, width=%i, %s\n", 34103b705cfSriastradh word - 11, 34203b705cfSriastradh data[i]>>21, (data[i]>>10)&0x3ff, 34303b705cfSriastradh data[i]&2?(data[i]&1?"y-tiled":"x-tiled"):""); 34403b705cfSriastradh i++; 34503b705cfSriastradh kgem_debug_print(data, offset, i, "TM%dS2: pitch=%i, \n", 34603b705cfSriastradh word - 11, 34703b705cfSriastradh ((data[i]>>21) + 1)*4); 34803b705cfSriastradh i++; 34903b705cfSriastradh kgem_debug_print(data, offset, i++, "TM%dS3\n", word - 11); 35003b705cfSriastradh kgem_debug_print(data, offset, i++, "TM%dS4: dflt color\n", word - 11); 35103b705cfSriastradh } 35203b705cfSriastradh } 35303b705cfSriastradh } 35403b705cfSriastradh assert (len == i); 35503b705cfSriastradh return len; 35603b705cfSriastradh case 0x00: 35703b705cfSriastradh kgem_debug_print(data, offset, 0, "3DSTATE_MAP_STATE\n"); 35803b705cfSriastradh len = (data[0] & 0x0000003f) + 2; 35903b705cfSriastradh kgem_debug_print(data, offset, 1, "mask\n"); 36003b705cfSriastradh 36103b705cfSriastradh i = 2; 36203b705cfSriastradh for (map = 0; map <= 15; map++) { 36303b705cfSriastradh if (data[1] & (1 << map)) { 36403b705cfSriastradh int width, height, pitch, dword; 36503b705cfSriastradh const char *tiling; 36603b705cfSriastradh 36703b705cfSriastradh dword = data[i]; 36803b705cfSriastradh kgem_debug_print(data, offset, i++, "map %d MS2 %s%s%s\n", map, 36903b705cfSriastradh dword&(1<<31)?"untrusted surface, ":"", 37003b705cfSriastradh dword&(1<<1)?"vertical line stride enable, ":"", 37103b705cfSriastradh dword&(1<<0)?"vertical ofs enable, ":""); 37203b705cfSriastradh 37303b705cfSriastradh dword = data[i]; 37403b705cfSriastradh width = ((dword >> 10) & ((1 << 11) - 1))+1; 37503b705cfSriastradh height = ((dword >> 21) & ((1 << 11) - 1))+1; 37603b705cfSriastradh 37703b705cfSriastradh tiling = "none"; 37803b705cfSriastradh if (dword & (1 << 2)) 37903b705cfSriastradh tiling = "fenced"; 38003b705cfSriastradh else if (dword & (1 << 1)) 38103b705cfSriastradh tiling = dword & (1 << 0) ? "Y" : "X"; 38203b705cfSriastradh type = " BAD"; 38303b705cfSriastradh format = "BAD"; 38403b705cfSriastradh switch ((dword>>7) & 0x7) { 38503b705cfSriastradh case 1: 38603b705cfSriastradh type = "8b"; 38703b705cfSriastradh switch ((dword>>3) & 0xf) { 38803b705cfSriastradh case 0: format = "I"; break; 38903b705cfSriastradh case 1: format = "L"; break; 39003b705cfSriastradh case 2: format = "A"; break; 39103b705cfSriastradh case 3: format = " mono"; break; } 39203b705cfSriastradh break; 39303b705cfSriastradh case 2: 39403b705cfSriastradh type = "16b"; 39503b705cfSriastradh switch ((dword>>3) & 0xf) { 39603b705cfSriastradh case 0: format = " rgb565"; break; 39703b705cfSriastradh case 1: format = " argb1555"; break; 39803b705cfSriastradh case 2: format = " argb4444"; break; 39903b705cfSriastradh case 5: format = " ay88"; break; 40003b705cfSriastradh case 6: format = " bump655"; break; 40103b705cfSriastradh case 7: format = "I"; break; 40203b705cfSriastradh case 8: format = "L"; break; 40303b705cfSriastradh case 9: format = "A"; break; } 40403b705cfSriastradh break; 40503b705cfSriastradh case 3: 40603b705cfSriastradh type = "32b"; 40703b705cfSriastradh switch ((dword>>3) & 0xf) { 40803b705cfSriastradh case 0: format = " argb8888"; break; 40903b705cfSriastradh case 1: format = " abgr8888"; break; 41003b705cfSriastradh case 2: format = " xrgb8888"; break; 41103b705cfSriastradh case 3: format = " xbgr8888"; break; 41203b705cfSriastradh case 4: format = " qwvu8888"; break; 41303b705cfSriastradh case 5: format = " axvu8888"; break; 41403b705cfSriastradh case 6: format = " lxvu8888"; break; 41503b705cfSriastradh case 7: format = " xlvu8888"; break; 41603b705cfSriastradh case 8: format = " argb2101010"; break; 41703b705cfSriastradh case 9: format = " abgr2101010"; break; 41803b705cfSriastradh case 10: format = " awvu2101010"; break; 41903b705cfSriastradh case 11: format = " gr1616"; break; 42003b705cfSriastradh case 12: format = " vu1616"; break; 42103b705cfSriastradh case 13: format = " xI824"; break; 42203b705cfSriastradh case 14: format = " xA824"; break; 42303b705cfSriastradh case 15: format = " xL824"; break; } 42403b705cfSriastradh break; 42503b705cfSriastradh case 5: 42603b705cfSriastradh type = "422"; 42703b705cfSriastradh switch ((dword>>3) & 0xf) { 42803b705cfSriastradh case 0: format = " yuv_swapy"; break; 42903b705cfSriastradh case 1: format = " yuv"; break; 43003b705cfSriastradh case 2: format = " yuv_swapuv"; break; 43103b705cfSriastradh case 3: format = " yuv_swapuvy"; break; } 43203b705cfSriastradh break; 43303b705cfSriastradh case 6: 43403b705cfSriastradh type = "compressed"; 43503b705cfSriastradh switch ((dword>>3) & 0x7) { 43603b705cfSriastradh case 0: format = " dxt1"; break; 43703b705cfSriastradh case 1: format = " dxt2_3"; break; 43803b705cfSriastradh case 2: format = " dxt4_5"; break; 43903b705cfSriastradh case 3: format = " fxt1"; break; 44003b705cfSriastradh case 4: format = " dxt1_rb"; break; } 44103b705cfSriastradh break; 44203b705cfSriastradh case 7: 44303b705cfSriastradh type = "4b indexed"; 44403b705cfSriastradh switch ((dword>>3) & 0xf) { 44503b705cfSriastradh case 7: format = " argb8888"; break; } 44603b705cfSriastradh break; 44703b705cfSriastradh } 44803b705cfSriastradh dword = data[i]; 44903b705cfSriastradh kgem_debug_print(data, offset, i++, "map %d MS3 [width=%d, height=%d, format=%s%s, tiling=%s%s]\n", 45003b705cfSriastradh map, width, height, type, format, tiling, 45103b705cfSriastradh dword&(1<<9)?" palette select":""); 45203b705cfSriastradh 45303b705cfSriastradh dword = data[i]; 45403b705cfSriastradh pitch = 4*(((dword >> 21) & ((1 << 11) - 1))+1); 45503b705cfSriastradh kgem_debug_print(data, offset, i++, "map %d MS4 [pitch=%d, max_lod=%i, vol_depth=%i, cube_face_ena=%x, %s]\n", 45603b705cfSriastradh map, pitch, 45703b705cfSriastradh (dword>>9)&0x3f, dword&0xff, (dword>>15)&0x3f, 45803b705cfSriastradh dword&(1<<8)?"miplayout legacy":"miplayout right"); 45903b705cfSriastradh } 46003b705cfSriastradh } 46103b705cfSriastradh assert (len == i); 46203b705cfSriastradh return len; 46303b705cfSriastradh case 0x85: 46403b705cfSriastradh len = (data[0] & 0x0000000f) + 2; 46503b705cfSriastradh assert (len == 2); 46603b705cfSriastradh kgem_debug_print(data, offset, 0, 46703b705cfSriastradh "3DSTATE_DEST_BUFFER_VARIABLES\n"); 46803b705cfSriastradh 46903b705cfSriastradh switch ((data[1] >> 8) & 0xf) { 47003b705cfSriastradh case 0x0: format = "g8"; break; 47103b705cfSriastradh case 0x1: format = "x1r5g5b5"; break; 47203b705cfSriastradh case 0x2: format = "r5g6b5"; break; 47303b705cfSriastradh case 0x3: format = "a8r8g8b8"; break; 47403b705cfSriastradh case 0x4: format = "ycrcb_swapy"; break; 47503b705cfSriastradh case 0x5: format = "ycrcb_normal"; break; 47603b705cfSriastradh case 0x6: format = "ycrcb_swapuv"; break; 47703b705cfSriastradh case 0x7: format = "ycrcb_swapuvy"; break; 47803b705cfSriastradh case 0x8: format = "a4r4g4b4"; break; 47903b705cfSriastradh case 0x9: format = "a1r5g5b5"; break; 48003b705cfSriastradh case 0xa: format = "a2r10g10b10"; break; 48103b705cfSriastradh default: format = "BAD"; break; 48203b705cfSriastradh } 48303b705cfSriastradh switch ((data[1] >> 2) & 0x3) { 48403b705cfSriastradh case 0x0: zformat = "u16"; break; 48503b705cfSriastradh case 0x1: zformat = "f16"; break; 48603b705cfSriastradh case 0x2: zformat = "u24x8"; break; 48703b705cfSriastradh default: zformat = "BAD"; break; 48803b705cfSriastradh } 48903b705cfSriastradh kgem_debug_print(data, offset, 1, "%s format, %s depth format, early Z %sabled\n", 49003b705cfSriastradh format, zformat, 49103b705cfSriastradh (data[1] & (1 << 31)) ? "en" : "dis"); 49203b705cfSriastradh return len; 49303b705cfSriastradh 49403b705cfSriastradh case 0x8e: 49503b705cfSriastradh { 49603b705cfSriastradh const char *name, *tiling; 49703b705cfSriastradh 49803b705cfSriastradh len = (data[0] & 0x0000000f) + 2; 49903b705cfSriastradh assert (len == 3); 50003b705cfSriastradh 50103b705cfSriastradh switch((data[1] >> 24) & 0x7) { 50203b705cfSriastradh case 0x3: name = "color"; break; 50303b705cfSriastradh case 0x7: name = "depth"; break; 50403b705cfSriastradh default: name = "unknown"; break; 50503b705cfSriastradh } 50603b705cfSriastradh 50703b705cfSriastradh tiling = "none"; 50803b705cfSriastradh if (data[1] & (1 << 23)) 50903b705cfSriastradh tiling = "fenced"; 51003b705cfSriastradh else if (data[1] & (1 << 22)) 51103b705cfSriastradh tiling = data[1] & (1 << 21) ? "Y" : "X"; 51203b705cfSriastradh 51303b705cfSriastradh kgem_debug_print(data, offset, 0, "3DSTATE_BUFFER_INFO\n"); 51403b705cfSriastradh kgem_debug_print(data, offset, 1, "%s, tiling = %s, pitch=%d\n", name, tiling, data[1]&0xffff); 51503b705cfSriastradh 51603b705cfSriastradh kgem_debug_print(data, offset, 2, "address\n"); 51703b705cfSriastradh return len; 51803b705cfSriastradh } 51903b705cfSriastradh 52003b705cfSriastradh case 0x81: 52103b705cfSriastradh len = (data[0] & 0x0000000f) + 2; 52203b705cfSriastradh assert (len == 3); 52303b705cfSriastradh 52403b705cfSriastradh kgem_debug_print(data, offset, 0, 52503b705cfSriastradh "3DSTATE_SCISSOR_RECTANGLE\n"); 52603b705cfSriastradh kgem_debug_print(data, offset, 1, "(%d,%d)\n", 52703b705cfSriastradh data[1] & 0xffff, data[1] >> 16); 52803b705cfSriastradh kgem_debug_print(data, offset, 2, "(%d,%d)\n", 52903b705cfSriastradh data[2] & 0xffff, data[2] >> 16); 53003b705cfSriastradh return len; 53103b705cfSriastradh 53203b705cfSriastradh case 0x80: 53303b705cfSriastradh len = (data[0] & 0x0000000f) + 2; 53403b705cfSriastradh assert (len == 5); 53503b705cfSriastradh 53603b705cfSriastradh kgem_debug_print(data, offset, 0, 53703b705cfSriastradh "3DSTATE_DRAWING_RECTANGLE\n"); 53803b705cfSriastradh kgem_debug_print(data, offset, 1, "%s\n", 53903b705cfSriastradh data[1]&(1<<30)?"depth ofs disabled ":""); 54003b705cfSriastradh kgem_debug_print(data, offset, 2, "(%d,%d)\n", 54103b705cfSriastradh data[2] & 0xffff, data[2] >> 16); 54203b705cfSriastradh kgem_debug_print(data, offset, 3, "(%d,%d)\n", 54303b705cfSriastradh data[3] & 0xffff, data[3] >> 16); 54403b705cfSriastradh kgem_debug_print(data, offset, 4, "(%d,%d)\n", 54503b705cfSriastradh data[4] & 0xffff, data[4] >> 16); 54603b705cfSriastradh return len; 54703b705cfSriastradh 54803b705cfSriastradh case 0x9c: 54903b705cfSriastradh len = (data[0] & 0x0000000f) + 2; 55003b705cfSriastradh assert (len == 7); 55103b705cfSriastradh 55203b705cfSriastradh kgem_debug_print(data, offset, 0, 55303b705cfSriastradh "3DSTATE_CLEAR_PARAMETERS\n"); 55403b705cfSriastradh kgem_debug_print(data, offset, 1, "prim_type=%s, clear=%s%s%s\n", 55503b705cfSriastradh data[1]&(1<<16)?"CLEAR_RECT":"ZONE_INIT", 55603b705cfSriastradh data[1]&(1<<2)?"color,":"", 55703b705cfSriastradh data[1]&(1<<1)?"depth,":"", 55803b705cfSriastradh data[1]&(1<<0)?"stencil,":""); 55903b705cfSriastradh kgem_debug_print(data, offset, 2, "clear color\n"); 56003b705cfSriastradh kgem_debug_print(data, offset, 3, "clear depth/stencil\n"); 56103b705cfSriastradh kgem_debug_print(data, offset, 4, "color value (rgba8888)\n"); 56203b705cfSriastradh kgem_debug_print(data, offset, 5, "depth value %f\n", 56303b705cfSriastradh int_as_float(data[5])); 56403b705cfSriastradh kgem_debug_print(data, offset, 6, "clear stencil\n"); 56503b705cfSriastradh return len; 56603b705cfSriastradh } 56703b705cfSriastradh 56803b705cfSriastradh for (idx = 0; idx < ARRAY_SIZE(opcodes_3d_1d); idx++) { 56903b705cfSriastradh opcode_3d_1d = &opcodes_3d_1d[idx]; 57003b705cfSriastradh if (((data[0] & 0x00ff0000) >> 16) == opcode_3d_1d->opcode) { 57103b705cfSriastradh len = 1; 57203b705cfSriastradh 57303b705cfSriastradh kgem_debug_print(data, offset, 0, "%s\n", opcode_3d_1d->name); 57403b705cfSriastradh if (opcode_3d_1d->max_len > 1) { 57503b705cfSriastradh len = (data[0] & 0x0000ffff) + 2; 57603b705cfSriastradh assert (len >= opcode_3d_1d->min_len && 57703b705cfSriastradh len <= opcode_3d_1d->max_len); 57803b705cfSriastradh } 57903b705cfSriastradh 58003b705cfSriastradh for (i = 1; i < len; i++) 58103b705cfSriastradh kgem_debug_print(data, offset, i, "dword %d\n", i); 58203b705cfSriastradh 58303b705cfSriastradh return len; 58403b705cfSriastradh } 58503b705cfSriastradh } 58603b705cfSriastradh 58703b705cfSriastradh kgem_debug_print(data, offset, 0, "3D UNKNOWN: 3d_1d opcode = 0x%x\n", opcode); 58803b705cfSriastradh return 1; 58903b705cfSriastradh} 59003b705cfSriastradh 59103b705cfSriastradhstatic int 59203b705cfSriastradhdecode_3d_1c(struct kgem *kgem, uint32_t offset) 59303b705cfSriastradh{ 59403b705cfSriastradh uint32_t *data = kgem->batch + offset; 59503b705cfSriastradh uint32_t opcode; 59603b705cfSriastradh 59703b705cfSriastradh opcode = (data[0] & 0x00f80000) >> 19; 59803b705cfSriastradh 59903b705cfSriastradh switch (opcode) { 60003b705cfSriastradh case 0x11: 60103b705cfSriastradh kgem_debug_print(data, offset, 0, "3DSTATE_DEPTH_SUBRECTANGLE_DISABLE\n"); 60203b705cfSriastradh return 1; 60303b705cfSriastradh case 0x10: 60403b705cfSriastradh kgem_debug_print(data, offset, 0, "3DSTATE_SCISSOR_ENABLE %s\n", 60503b705cfSriastradh data[0]&1?"enabled":"disabled"); 60603b705cfSriastradh return 1; 60703b705cfSriastradh case 0x01: 60803b705cfSriastradh kgem_debug_print(data, offset, 0, "3DSTATE_MAP_COORD_SET_I830\n"); 60903b705cfSriastradh return 1; 61003b705cfSriastradh case 0x0a: 61103b705cfSriastradh kgem_debug_print(data, offset, 0, "3DSTATE_MAP_CUBE_I830\n"); 61203b705cfSriastradh return 1; 61303b705cfSriastradh case 0x05: 61403b705cfSriastradh kgem_debug_print(data, offset, 0, "3DSTATE_MAP_TEX_STREAM_I830\n"); 61503b705cfSriastradh return 1; 61603b705cfSriastradh } 61703b705cfSriastradh 61803b705cfSriastradh kgem_debug_print(data, offset, 0, "3D UNKNOWN: 3d_1c opcode = 0x%x\n", 61903b705cfSriastradh opcode); 62003b705cfSriastradh return 1; 62103b705cfSriastradh} 62203b705cfSriastradh 62303b705cfSriastradhint kgem_gen2_decode_3d(struct kgem *kgem, uint32_t offset) 62403b705cfSriastradh{ 62503b705cfSriastradh const static struct { 62603b705cfSriastradh uint32_t opcode; 62703b705cfSriastradh int min_len; 62803b705cfSriastradh int max_len; 62903b705cfSriastradh const char *name; 63003b705cfSriastradh } opcodes[] = { 63103b705cfSriastradh { 0x02, 1, 1, "3DSTATE_MODES_3" }, 63203b705cfSriastradh { 0x03, 1, 1, "3DSTATE_ENABLES_1"}, 63303b705cfSriastradh { 0x04, 1, 1, "3DSTATE_ENABLES_2"}, 63403b705cfSriastradh { 0x05, 1, 1, "3DSTATE_VFT0"}, 63503b705cfSriastradh { 0x06, 1, 1, "3DSTATE_AA"}, 63603b705cfSriastradh { 0x07, 1, 1, "3DSTATE_RASTERIZATION_RULES" }, 63703b705cfSriastradh { 0x08, 1, 1, "3DSTATE_MODES_1" }, 63803b705cfSriastradh { 0x09, 1, 1, "3DSTATE_STENCIL_TEST" }, 63903b705cfSriastradh { 0x0a, 1, 1, "3DSTATE_VFT1"}, 64003b705cfSriastradh { 0x0b, 1, 1, "3DSTATE_INDPT_ALPHA_BLEND" }, 64103b705cfSriastradh { 0x0c, 1, 1, "3DSTATE_MODES_5" }, 64203b705cfSriastradh { 0x0d, 1, 1, "3DSTATE_MAP_BLEND_OP" }, 64303b705cfSriastradh { 0x0e, 1, 1, "3DSTATE_MAP_BLEND_ARG" }, 64403b705cfSriastradh { 0x0f, 1, 1, "3DSTATE_MODES_2" }, 64503b705cfSriastradh { 0x15, 1, 1, "3DSTATE_FOG_COLOR" }, 64603b705cfSriastradh { 0x16, 1, 1, "3DSTATE_MODES_4" }, 64703b705cfSriastradh }; 64803b705cfSriastradh uint32_t *data = kgem->batch + offset; 64903b705cfSriastradh uint32_t opcode = (data[0] & 0x1f000000) >> 24; 65003b705cfSriastradh uint32_t idx; 65103b705cfSriastradh 65203b705cfSriastradh switch (opcode) { 65303b705cfSriastradh case 0x1f: 65403b705cfSriastradh return decode_3d_primitive(kgem, offset); 65503b705cfSriastradh case 0x1d: 65603b705cfSriastradh return decode_3d_1d(kgem, offset); 65703b705cfSriastradh case 0x1c: 65803b705cfSriastradh return decode_3d_1c(kgem, offset); 65903b705cfSriastradh } 66003b705cfSriastradh 66103b705cfSriastradh /* Catch the known instructions */ 66203b705cfSriastradh for (idx = 0; idx < ARRAY_SIZE(opcodes); idx++) { 66303b705cfSriastradh if (opcode == opcodes[idx].opcode) { 66403b705cfSriastradh unsigned int len = 1, i; 66503b705cfSriastradh 66603b705cfSriastradh kgem_debug_print(data, offset, 0, "%s\n", opcodes[idx].name); 66703b705cfSriastradh if (opcodes[idx].max_len > 1) { 66803b705cfSriastradh len = (data[0] & 0xf) + 2; 66903b705cfSriastradh assert(len >= opcodes[idx].min_len && 67003b705cfSriastradh len <= opcodes[idx].max_len); 67103b705cfSriastradh } 67203b705cfSriastradh 67303b705cfSriastradh for (i = 1; i < len; i++) 67403b705cfSriastradh kgem_debug_print(data, offset, i, "dword %d\n", i); 67503b705cfSriastradh return len; 67603b705cfSriastradh } 67703b705cfSriastradh } 67803b705cfSriastradh 67903b705cfSriastradh kgem_debug_print(data, offset, 0, "3D UNKNOWN: 3d opcode = 0x%x\n", opcode); 68003b705cfSriastradh return 1; 68103b705cfSriastradh} 68203b705cfSriastradh 68303b705cfSriastradhvoid kgem_gen2_finish_state(struct kgem *kgem) 68403b705cfSriastradh{ 68503b705cfSriastradh memset(&state, 0, sizeof(state)); 68603b705cfSriastradh} 687