/* Applies to tiler_gl_enables */
-#define MALI_CULL_FACE_BACK 0x80
-#define MALI_CULL_FACE_FRONT 0x40
-#define MALI_FRONT_FACE(v) (v << 5)
-#define MALI_CCW (0)
-#define MALI_CW (1)
+#define MALI_OCCLUSION_QUERY (1 << 3)
+#define MALI_OCCLUSION_PRECISE (1 << 4)
-#define MALI_OCCLUSION_BOOLEAN 0x8
+/* Set for a glFrontFace(GL_CCW) in a Y=0=TOP coordinate system (like Gallium).
+ * In OpenGL, this would corresponds to glFrontFace(GL_CW). Mesa and the blob
+ * disagree about how to do viewport flipping, so the blob actually sets this
+ * for GL_CW but then has a negative viewport stride */
+#define MALI_FRONT_CCW_TOP (1 << 5)
+
+#define MALI_CULL_FACE_FRONT (1 << 6)
+#define MALI_CULL_FACE_BACK (1 << 7)
/* TODO: Might this actually be a finer bitfield? */
#define MALI_DEPTH_STENCIL_ENABLE 0x6400
/* Corresponds to MALI_MASK_* above and glColorMask arguments */
unsigned color_mask : 4;
-
- /* Attached constant for CONSTANT_ALPHA, etc */
-
-#ifndef BIFROST
- float constant;
-#endif
} __attribute__((packed));
/* Used with channel swizzling */
* bits mean.
*/
+#define MALI_CHANNEL_4 2
+
#define MALI_CHANNEL_8 3
#define MALI_CHANNEL_16 4
#define MALI_CHANNEL_FLOAT 7
enum mali_format {
+ MALI_RGB565 = MALI_FORMAT_SPECIAL | 0x0,
+ MALI_RGB5_A1_UNORM = MALI_FORMAT_SPECIAL | 0x2,
MALI_RGB10_A2_UNORM = MALI_FORMAT_SPECIAL | 0x3,
MALI_RGB10_A2_SNORM = MALI_FORMAT_SPECIAL | 0x5,
MALI_RGB10_A2UI = MALI_FORMAT_SPECIAL | 0x7,
MALI_RGB16_UNORM = MALI_FORMAT_UNORM | MALI_NR_CHANNELS(3) | MALI_CHANNEL_16,
MALI_RGB32_UNORM = MALI_FORMAT_UNORM | MALI_NR_CHANNELS(3) | MALI_CHANNEL_32,
MALI_RGB32F = MALI_FORMAT_UNORM | MALI_NR_CHANNELS(3) | MALI_CHANNEL_FLOAT,
+ MALI_RGBA4_UNORM = MALI_FORMAT_UNORM | MALI_NR_CHANNELS(4) | MALI_CHANNEL_4,
MALI_RGBA8_UNORM = MALI_FORMAT_UNORM | MALI_NR_CHANNELS(4) | MALI_CHANNEL_8,
MALI_RGBA16_UNORM = MALI_FORMAT_UNORM | MALI_NR_CHANNELS(4) | MALI_CHANNEL_16,
MALI_RGBA32_UNORM = MALI_FORMAT_UNORM | MALI_NR_CHANNELS(4) | MALI_CHANNEL_32,
/* Applies to unknown1 */
#define MALI_NO_ALPHA_TO_COVERAGE (1 << 10)
-struct mali_blend_meta {
-#ifndef BIFROST
- /* Base value of 0x200.
+/* Flags denoting the fragment shader's use of tilebuffer readback. If the
+ * shader might read any part of the tilebuffer, set MALI_READS_TILEBUFFER. If
+ * it might read depth/stencil in particular, also set MALI_READS_ZS */
+
+#define MALI_READS_ZS (1 << 12)
+#define MALI_READS_TILEBUFFER (1 << 16)
+
+/* The raw Midgard blend payload can either be an equation or a shader
+ * address, depending on the context */
+
+union midgard_blend {
+ mali_ptr shader;
+
+ struct {
+ struct mali_blend_equation equation;
+ float constant;
+ };
+};
+
+/* On MRT Midgard systems (using an MFBD), each render target gets its own
+ * blend descriptor */
+
+struct midgard_blend_rt {
+ /* Flags base value of 0x200 to enable the render target.
* OR with 0x1 for blending (anything other than REPLACE).
- * OR with 0x2 for programmable blending
+ * OR with 0x2 for programmable blending with 0-2 registers
+ * OR with 0x3 for programmable blending with 2+ registers
*/
- u64 unk1;
+ u64 flags;
+ union midgard_blend blend;
+} __attribute__((packed));
+
+/* On Bifrost systems (all MRT), each render target gets one of these
+ * descriptors */
+
+struct bifrost_blend_rt {
+ /* This is likely an analogue of the flags on
+ * midgard_blend_rt */
+
+ u16 flags; // = 0x200
+
+ /* Single-channel blend constants are encoded in a sort of
+ * fixed-point. Basically, the float is mapped to a byte, becoming
+ * a high byte, and then the lower-byte is added for precision.
+ * For the original float f:
+ *
+ * f = (constant_hi / 255) + (constant_lo / 65535)
+ *
+ * constant_hi = int(f / 255)
+ * constant_lo = 65535*f - (65535/255) * constant_hi
+ */
- /* For programmable blending, these turn into the blend_shader address */
- struct mali_blend_equation blend_equation_1;
+ u16 constant;
- u64 zero2;
- struct mali_blend_equation blend_equation_2;
-#else
- u32 unk1; // = 0x200
- struct mali_blend_equation blend_equation;
+ struct mali_blend_equation equation;
/*
* - 0x19 normally
* - 0x3 when this slot is unused (everything else is 0 except the index)
* in the same pool as the original shader. The kernel will
* make sure this allocation is aligned to 2^24 bytes.
*/
- u32 blend_shader;
+ u32 shader;
};
-#endif
} __attribute__((packed));
+/* Descriptor for the shader. Following this is at least one, up to four blend
+ * descriptors for each active render target */
+
struct mali_shader_meta {
mali_ptr shader;
u16 texture_count;
* MALI_HAS_BLEND_SHADER to decide how to interpret.
*/
- union {
- mali_ptr blend_shader;
- struct mali_blend_equation blend_equation;
- };
-
- /* There can be up to 4 blend_meta's. None of them are required for
- * vertex shaders or the non-MRT case for Midgard (so the blob doesn't
- * allocate any space).
- */
- struct mali_blend_meta blend_meta[];
-
+ union midgard_blend blend;
} __attribute__((packed));
/* This only concerns hardware jobs */
MALI_ATTR_NPOT_DIVIDE = 4,
};
+/* This magic "pseudo-address" is used as `elements` to implement
+ * gl_PointCoord. When read from a fragment shader, it generates a point
+ * coordinate per the OpenGL ES 2.0 specification. Flipped coordinate spaces
+ * require an affine transformation in the shader. */
+
+#define MALI_VARYING_POINT_COORD (0x60)
+
union mali_attr {
/* This is used for actual attributes. */
struct {
*/
/* Applies to unknown_draw */
+
#define MALI_DRAW_INDEXED_UINT8 (0x10)
#define MALI_DRAW_INDEXED_UINT16 (0x20)
#define MALI_DRAW_INDEXED_UINT32 (0x30)
#define MALI_DRAW_VARYING_SIZE (0x100)
+#define MALI_DRAW_PRIMITIVE_RESTART_FIXED_INDEX (0x10000)
struct mali_vertex_tiler_prefix {
/* This is a dynamic bitfield containing the following things in this order:
* in vertex and tiler jobs.
*/
mali_ptr framebuffer;
-
-#ifdef __LP64__
-#ifdef BIFROST
- /* most likely padding to make this a multiple of 64 bytes */
- u64 zero7;
-#endif
-#endif
} __attribute__((packed));
struct midgard_payload_vertex_tiler {
struct mali_vertex_tiler_prefix prefix;
struct bifrost_tiler_only tiler;
struct mali_vertex_tiler_postfix tiler_postfix;
+ u64 padding; /* zero */
struct bifrost_vertex_only vertex;
struct mali_vertex_tiler_postfix vertex_postfix;
} __attribute__((packed));
/* Cubemap bloats everything up */
#define MAX_FACES (6)
+/* For each pointer, there is an address and optionally also a stride */
+#define MAX_ELEMENTS (2)
+
/* Corresponds to the type passed to glTexImage2D and so forth */
+/* Flags for usage2 */
+#define MALI_TEX_MANUAL_STRIDE (0x20)
+
struct mali_texture_format {
unsigned swizzle : 12;
enum mali_format format : 8;
uint32_t unknown6;
uint32_t unknown7;
- mali_ptr swizzled_bitmaps[MAX_MIP_LEVELS * MAX_FACES];
+ mali_ptr payload[MAX_MIP_LEVELS * MAX_FACES * MAX_ELEMENTS];
} __attribute__((packed));
/* Used as part of filter_mode */
float border_color[4];
} __attribute__((packed));
-/* TODO: What are the floats? Apparently always { -inf, -inf, inf, inf },
- * unless the scissor test is enabled.
- *
- * viewport0/viewport1 form the arguments to glViewport. viewport1 is modified
- * by MALI_POSITIVE; viewport0 is as-is.
+/* viewport0/viewport1 form the arguments to glViewport. viewport1 is
+ * modified by MALI_POSITIVE; viewport0 is as-is.
*/
struct mali_viewport {
- float floats[4];
+ /* XY clipping planes */
+ float clip_minx;
+ float clip_miny;
+ float clip_maxx;
+ float clip_maxy;
- float depth_range_n;
- float depth_range_f;
+ /* Depth clipping planes */
+ float clip_minz;
+ float clip_maxz;
u16 viewport0[2];
u16 viewport1[2];
} __attribute__((packed));
-/* TODO: Varying meta is symmetrical with attr_meta, but there is some
- * weirdness associated. Figure it out. */
-
-struct mali_unknown6 {
- u64 unknown0;
- u64 unknown1;
-};
-
/* From presentations, 16x16 tiles externally. Use shift for fast computation
* of tile numbers. */
mali_ptr framebuffer;
} __attribute__((packed));
-/* (Single?) Framebuffer Descriptor */
+/* Single Framebuffer Descriptor */
/* Flags apply to format. With just MSAA_A and MSAA_B, the framebuffer is
* configured for 4x. With MSAA_8, it is configured for 8x. */
/* More below this, maybe */
} __attribute__((packed));
-/* Format bits for the render target */
+/* Format bits for the render target flags */
-#define MALI_MFBD_FORMAT_AFBC (1 << 10)
-#define MALI_MFBD_FORMAT_MSAA (1 << 12)
-#define MALI_MFBD_FORMAT_NO_ALPHA (1 << 25)
+#define MALI_MFBD_FORMAT_AFBC (1 << 5)
+#define MALI_MFBD_FORMAT_MSAA (1 << 7)
+
+struct mali_rt_format {
+ unsigned unk1 : 32;
+ unsigned unk2 : 3;
+
+ unsigned nr_channels : 2; /* MALI_POSITIVE */
+
+ unsigned flags : 11;
+
+ unsigned swizzle : 12;
+
+ unsigned unk4 : 4;
+} __attribute__((packed));
struct bifrost_render_target {
- u32 unk1; // = 0x4000000
- u32 format;
+ struct mali_rt_format format;
u64 zero1;
* - TODO: Anything else?
*/
+/* Flags field: note, these are guesses */
+
+#define MALI_EXTRA_PRESENT (0x400)
+#define MALI_EXTRA_AFBC (0x20)
+#define MALI_EXTRA_AFBC_ZS (0x10)
+#define MALI_EXTRA_ZS (0x4)
+
struct bifrost_fb_extra {
mali_ptr checksum;
/* Each tile has an 8 byte checksum, so the stride is "width in tiles * 8" */
u32 checksum_stride;
- u32 unk;
+ u32 flags;
union {
/* Note: AFBC is only allowed for 24/8 combined depth/stencil. */
} __attribute__((packed));
/* flags for unk3 */
+
+/* Enables writing depth results back to main memory (rather than keeping them
+ * on-chip in the tile buffer and then discarding) */
+
+#define MALI_MFBD_DEPTH_WRITE (1 << 10)
+
+/* The MFBD contains the extra bifrost_fb_extra section */
+
#define MALI_MFBD_EXTRA (1 << 13)
struct bifrost_framebuffer {