#include "util/u_format.h"
#include "indices/u_primconvert.h"
#include "tgsi/tgsi_parse.h"
+#include "util/u_math.h"
#include "pan_screen.h"
#include "pan_blending.h"
/* Do not actually send anything to the GPU; merely generate the cmdstream as fast as possible. Disables framebuffer writes */
//#define DRY_RUN
+/* Can a given format support AFBC? Not all can. */
+
+static bool
+panfrost_can_afbc(enum pipe_format format)
+{
+ const struct util_format_description *desc =
+ util_format_description(format);
+
+ if (util_format_is_rgba8_variant(desc))
+ return true;
+
+ /* TODO: AFBC of other formats */
+
+ return false;
+}
+
/* AFBC is enabled on a per-resource basis (AFBC enabling is theoretically
* indepdent between color buffers and depth/stencil). To enable, we allocate
* the AFBC metadata buffer and mark that it is enabled. We do -not- actually
ctx->pipe_framebuffer.cbufs[0]->texture->bind & PIPE_BIND_SHARED;
}
-/* Maps float 0.0-1.0 to int 0x00-0xFF */
-static uint8_t
-normalised_float_to_u8(float f)
+static uint32_t
+pan_pack_color(const union pipe_color_union *color, enum pipe_format format)
{
- return (uint8_t) (int) (f * 255.0f);
+ /* Alpha magicked to 1.0 if there is no alpha */
+
+ bool has_alpha = util_format_has_alpha(format);
+ float clear_alpha = has_alpha ? color->f[3] : 1.0f;
+
+ /* Packed color depends on the framebuffer format */
+
+ const struct util_format_description *desc =
+ util_format_description(format);
+
+ if (util_format_is_rgba8_variant(desc)) {
+ return (float_to_ubyte(clear_alpha) << 24) |
+ (float_to_ubyte(color->f[2]) << 16) |
+ (float_to_ubyte(color->f[1]) << 8) |
+ (float_to_ubyte(color->f[0]) << 0);
+ } else if (format == PIPE_FORMAT_B5G6R5_UNORM) {
+ /* First, we convert the components to R5, G6, B5 separately */
+ unsigned r5 = CLAMP(color->f[0], 0.0, 1.0) * 31.0;
+ unsigned g6 = CLAMP(color->f[1], 0.0, 1.0) * 63.0;
+ unsigned b5 = CLAMP(color->f[2], 0.0, 1.0) * 31.0;
+
+ /* Then we pack into a sparse u32. TODO: Why these shifts? */
+ return (b5 << 25) | (g6 << 14) | (r5 << 5);
+ } else {
+ /* Unknown format */
+ assert(0);
+ }
+
+ return 0;
}
static void
struct panfrost_job *job = panfrost_get_job_for_fbo(ctx);
if (buffers & PIPE_CLEAR_COLOR) {
- /* Alpha clear only meaningful without alpha channel, TODO less ad hoc */
- bool has_alpha = util_format_has_alpha(ctx->pipe_framebuffer.cbufs[0]->format);
- float clear_alpha = has_alpha ? color->f[3] : 1.0f;
-
- uint32_t packed_color =
- (normalised_float_to_u8(clear_alpha) << 24) |
- (normalised_float_to_u8(color->f[2]) << 16) |
- (normalised_float_to_u8(color->f[1]) << 8) |
- (normalised_float_to_u8(color->f[0]) << 0);
-
- job->clear_color = packed_color;
-
+ enum pipe_format format = ctx->pipe_framebuffer.cbufs[0]->format;
+ job->clear_color = pan_pack_color(color, format);
}
if (buffers & PIPE_CLEAR_DEPTH) {
panfrost_attach_vt_framebuffer(ctx);
struct panfrost_resource *tex = ((struct panfrost_resource *) ctx->pipe_framebuffer.cbufs[i]->texture);
+ enum pipe_format format = ctx->pipe_framebuffer.cbufs[i]->format;
bool is_scanout = panfrost_is_scanout(ctx);
- if (!is_scanout && tex->bo->layout != PAN_AFBC) {
+ if (!is_scanout && tex->bo->layout != PAN_AFBC && panfrost_can_afbc(format)) {
/* The blob is aggressive about enabling AFBC. As such,
* it's pretty much necessary to use it here, since we
* have no traces of non-compressed FBO. */
*out_transfer = &transfer->base;
- if (resource->bind & PIPE_BIND_DISPLAY_TARGET ||
- resource->bind & PIPE_BIND_SCANOUT ||
- resource->bind & PIPE_BIND_SHARED) {
- /* Mipmapped readpixels?! */
- assert(level == 0);
+ /* Check if we're bound for rendering and this is a read pixels. If so,
+ * we need to flush */
+
+ struct panfrost_context *ctx = pan_context(pctx);
+ struct pipe_framebuffer_state *fb = &ctx->pipe_framebuffer;
+
+ bool is_bound = false;
- /* Force a flush -- kill the pipeline */
+ for (unsigned c = 0; c < fb->nr_cbufs; ++c) {
+ is_bound |= fb->cbufs[c]->texture == resource;
+ }
+
+ if (is_bound && (usage & PIPE_TRANSFER_READ)) {
+ assert(level == 0);
panfrost_flush(pctx, NULL, PIPE_FLUSH_END_OF_FRAME);
}
+ /* TODO: Respect usage flags */
+
if (usage & PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE) {
/* TODO: reallocate */
//printf("debug: Missed reallocate\n");