panfrost: Support RGB565 FBOs
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
#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"
|
||||
@@ -53,6 +54,22 @@ extern const char *pan_counters_base;
|
||||
/* 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
|
||||
@@ -228,11 +245,38 @@ panfrost_is_scanout(struct panfrost_context *ctx)
|
||||
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
|
||||
@@ -246,18 +290,8 @@ panfrost_clear(
|
||||
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) {
|
||||
@@ -2071,9 +2105,10 @@ panfrost_set_framebuffer_state(struct pipe_context *pctx,
|
||||
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. */
|
||||
|
@@ -36,7 +36,7 @@ panfrost_mfbd_format(struct pipe_surface *surf)
|
||||
const struct util_format_description *desc =
|
||||
util_format_description(surf->texture->format);
|
||||
|
||||
/* Fill in accordingly */
|
||||
/* Fill in accordingly, defaulting to RGBA8888 (UNORM) */
|
||||
|
||||
struct mali_rt_format fmt = {
|
||||
.unk1 = 0x4000000,
|
||||
@@ -47,6 +47,14 @@ panfrost_mfbd_format(struct pipe_surface *surf)
|
||||
.unk4 = 0x8
|
||||
};
|
||||
|
||||
/* Set flags for alternative formats */
|
||||
|
||||
if (surf->texture->format == PIPE_FORMAT_B5G6R5_UNORM) {
|
||||
fmt.unk1 = 0x14000000;
|
||||
fmt.nr_channels = MALI_POSITIVE(2);
|
||||
fmt.flags |= 0x1;
|
||||
}
|
||||
|
||||
return fmt;
|
||||
}
|
||||
|
||||
@@ -95,7 +103,6 @@ panfrost_mfbd_set_cbuf(
|
||||
stride = -stride;
|
||||
}
|
||||
|
||||
/* MFBD specifies stride in tiles */
|
||||
rt->framebuffer = framebuffer;
|
||||
rt->framebuffer_stride = stride / 16;
|
||||
} else if (rsrc->bo->layout == PAN_AFBC) {
|
||||
|
@@ -416,16 +416,25 @@ panfrost_transfer_map(struct pipe_context *pctx,
|
||||
|
||||
*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 */
|
||||
|
||||
/* Force a flush -- kill the pipeline */
|
||||
struct panfrost_context *ctx = pan_context(pctx);
|
||||
struct pipe_framebuffer_state *fb = &ctx->pipe_framebuffer;
|
||||
|
||||
bool is_bound = false;
|
||||
|
||||
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");
|
||||
|
@@ -445,11 +445,11 @@ panfrost_is_format_supported( struct pipe_screen *screen,
|
||||
return FALSE;
|
||||
|
||||
if (bind & PIPE_BIND_RENDER_TARGET) {
|
||||
/* We don't support rendering into anything but RGBA8 yet. We
|
||||
* need more formats for spec compliance, but for now, honesty
|
||||
* is the best policy <3 */
|
||||
/* TODO: Support all the formats! :) */
|
||||
bool supported = util_format_is_rgba8_variant(format_desc);
|
||||
supported |= format == PIPE_FORMAT_B5G6R5_UNORM;
|
||||
|
||||
if (!util_format_is_rgba8_variant(format_desc))
|
||||
if (!supported)
|
||||
return FALSE;
|
||||
|
||||
if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS)
|
||||
|
Reference in New Issue
Block a user