summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLucas Stach <l.stach@pengutronix.de>2014-07-29 17:26:44 +0200
committerLucas Stach <l.stach@pengutronix.de>2014-07-30 12:22:54 +0200
commit77e635f9f4bc42100122263fbe2126a69583b403 (patch)
tree67ac72fe7775f24a53937a105a7afda7bb84a90e
parent980408b88c511354823db6a6060d29e8026b85f8 (diff)
downloadmesa-77e635f9f4bc42100122263fbe2126a69583b403.tar.gz
mesa-77e635f9f4bc42100122263fbe2126a69583b403.tar.xz
etna: use plain etna_resource to wrap framebuffer
This moves framebuffer handling almost completely into MESA and doesn't rely on libetna anymore. Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
-rw-r--r--src/gallium/drivers/etna/etna_screen.c24
-rw-r--r--src/gallium/drivers/etna/etna_screen.h13
-rw-r--r--src/gallium/winsys/etna/fbdev/etna_fbdev_winsys.c117
3 files changed, 105 insertions, 49 deletions
diff --git a/src/gallium/drivers/etna/etna_screen.c b/src/gallium/drivers/etna/etna_screen.c
index a3c8ed375c..591596a37e 100644
--- a/src/gallium/drivers/etna/etna_screen.c
+++ b/src/gallium/drivers/etna/etna_screen.c
@@ -432,16 +432,13 @@ static void etna_screen_flush_frontbuffer( struct pipe_screen *screen,
void *winsys_drawable_handle,
struct pipe_box *subbox)
{
- struct etna_rs_target *drawable = (struct etna_rs_target *)winsys_drawable_handle;
+ struct etna_resource *drawable = winsys_drawable_handle;
struct etna_resource *rt_resource = etna_resource(resource);
struct etna_pipe_context *ectx = rt_resource->last_ctx;
assert(level <= resource->last_level && layer < resource->array_size);
assert(ectx);
struct etna_ctx *ctx = ectx->ctx;
- /* release previous fence, make reference to fence if we need one */
- screen->fence_reference(screen, &drawable->fence, NULL);
-
etna_set_state(ctx, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_COLOR);
etna_stall(ctx, SYNC_RECIPIENT_RA, SYNC_RECIPIENT_PE);
@@ -475,25 +472,26 @@ static void etna_screen_flush_frontbuffer( struct pipe_screen *screen,
.source_addr[0] = etna_get_level_pipe_addr(rt_resource, level, 0),
.source_addr[1] = etna_get_level_pipe_addr(rt_resource, level, 1),
.source_stride = rt_resource->levels[level].stride,
- .dest_format = drawable->rs_format,
- .dest_tiling = ETNA_LAYOUT_LINEAR,
+ .dest_format = translate_rt_format(drawable->base.format, false),
+ .dest_tiling = drawable->layout,
.dest_addr[0] = etna_bo_gpu_address(drawable->bo),
- .dest_stride = drawable->stride,
+ .dest_stride = drawable->levels[0].stride,
.downsample_x = msaa_xscale > 1,
.downsample_y = msaa_yscale > 1,
- .swap_rb = drawable->swap_rb,
+ .swap_rb = translate_rb_src_dst_swap(rt_resource->base.format,
+ drawable->base.format),
.dither = {0xffffffff, 0xffffffff}, // XXX dither when going from 24 to 16 bit?
.clear_mode = VIVS_RS_CLEAR_CONTROL_MODE_DISABLED,
- .width = drawable->width * msaa_xscale,
- .height = drawable->height * msaa_yscale
+ .width = drawable->levels[0].width * msaa_xscale,
+ .height = drawable->levels[0].height * msaa_yscale
});
etna_submit_rs_state(ctx, &copy_to_screen);
DBG_F(ETNA_DBG_FRAME_MSGS,
"Queued RS command to flush screen from %08x to %08x stride=%08x width=%i height=%i, ctx %p",
etna_bo_gpu_address(rt_resource->bo) + rt_resource->levels[level].offset,
- etna_bo_gpu_address(drawable->bo), drawable->stride,
- drawable->width, drawable->height, ctx);
- ectx->base.flush(&ectx->base, &drawable->fence, 0);
+ etna_bo_gpu_address(drawable->bo), drawable->levels[0].stride,
+ drawable->levels[0].width, drawable->levels[0].height, ctx);
+ ectx->base.flush(&ectx->base, NULL, 0);
}
struct pipe_screen *
diff --git a/src/gallium/drivers/etna/etna_screen.h b/src/gallium/drivers/etna/etna_screen.h
index 80ccd2cf0a..81c5281b82 100644
--- a/src/gallium/drivers/etna/etna_screen.h
+++ b/src/gallium/drivers/etna/etna_screen.h
@@ -41,19 +41,6 @@ struct etna_screen {
struct etna_pipe_specs specs;
};
-/* Resolve target.
- * Used by etna_screen_flush_frontbuffer
- */
-struct etna_rs_target
-{
- unsigned rs_format;
- bool swap_rb;
- unsigned width, height;
- struct etna_bo *bo;
- size_t stride;
- struct pipe_fence_handle *fence;
-};
-
static INLINE struct etna_screen *
etna_screen(struct pipe_screen *pscreen)
{
diff --git a/src/gallium/winsys/etna/fbdev/etna_fbdev_winsys.c b/src/gallium/winsys/etna/fbdev/etna_fbdev_winsys.c
index ea92712ae2..da22458d90 100644
--- a/src/gallium/winsys/etna/fbdev/etna_fbdev_winsys.c
+++ b/src/gallium/winsys/etna/fbdev/etna_fbdev_winsys.c
@@ -9,6 +9,7 @@
#include "etna_fbdev_public.h"
#include "etna/etna_screen.h"
+#include "etna/etna_pipe.h"
#include <etnaviv/viv.h>
#include <etnaviv/etna_bo.h>
@@ -24,14 +25,81 @@ struct etna_fbdev_screen
/* anything? */
};
-static inline struct etna_fbdev_screen *etna_fbdev_screen(struct native_fbdev_screen *fbdev_screen)
+static void etna_fbdev_screen_destroy(struct native_fbdev_screen *fbdev_screen)
{
- return (struct etna_fbdev_screen*)fbdev_screen;
+ FREE(fbdev_screen);
}
-static void etna_fbdev_screen_destroy(struct native_fbdev_screen *fbdev_screen)
+struct etna_fb_format_desc
{
- FREE(fbdev_screen);
+ unsigned bits_per_pixel;
+ unsigned red_offset;
+ unsigned red_length;
+ unsigned green_offset;
+ unsigned green_length;
+ unsigned blue_offset;
+ unsigned blue_length;
+ unsigned alpha_offset;
+ unsigned alpha_length;
+ enum pipe_format format;
+};
+
+static const struct etna_fb_format_desc etna_fb_formats[] = {
+/* bpp ro rl go gl bo bl ao al gs format */
+ {32, 16, 8, 8, 8, 0 , 8, 0, 0, PIPE_FORMAT_B8G8R8X8_UNORM},
+ {32, 0 , 8, 8, 8, 16, 8, 0, 0, PIPE_FORMAT_R8G8B8X8_UNORM},
+ {32, 16, 8, 8, 8, 0 , 8, 24, 8, PIPE_FORMAT_B8G8R8A8_UNORM},
+ {32, 0 , 8, 8, 8, 16, 8, 24, 8, PIPE_FORMAT_R8G8B8A8_UNORM},
+ {16, 8 , 4, 4, 4, 0, 4, 12, 4, PIPE_FORMAT_B4G4R4A4_UNORM},
+ {16, 10, 5, 5, 5, 0, 5, 0, 0, PIPE_FORMAT_B5G5R5X1_UNORM},
+ {16, 10, 5, 5, 5, 0, 5, 15, 1, PIPE_FORMAT_B5G5R5A1_UNORM},
+ {16, 11, 5, 5, 6, 0, 5, 0, 0, PIPE_FORMAT_B5G6R5_UNORM },
+};
+
+#define NUM_FB_FORMATS (sizeof(etna_fb_formats) / sizeof(etna_fb_formats[0]))
+
+/* Get resolve format and swap red/blue format based on report on red/green/blue
+ * bit positions from kernel.
+ */
+static enum pipe_format etna_fbdev_get_format(const struct fb_var_screeninfo *fb_var)
+{
+ int fmt_idx = 0;
+
+ if (fb_var->grayscale)
+ return PIPE_FORMAT_COUNT;
+
+ /* linear scan of table to find matching format */
+ for (fmt_idx = 0; fmt_idx<NUM_FB_FORMATS; ++fmt_idx)
+ {
+ const struct etna_fb_format_desc *desc = &etna_fb_formats[fmt_idx];
+ if(desc->red_offset == fb_var->red.offset &&
+ desc->red_length == fb_var->red.length &&
+ desc->green_offset == fb_var->green.offset &&
+ desc->green_length == fb_var->green.length &&
+ desc->blue_offset == fb_var->blue.offset &&
+ desc->blue_length == fb_var->blue.length &&
+ (desc->alpha_offset == fb_var->transp.offset || desc->alpha_length == 0) &&
+ desc->alpha_length == fb_var->transp.length)
+ {
+ break;
+ }
+ }
+ /* no matching format found */
+ if (fmt_idx == NUM_FB_FORMATS)
+ {
+ printf("Unsupported framebuffer format: red_offset=%i red_length=%i green_offset=%i green_length=%i blue_offset=%i blue_length=%i trans_offset=%i transp_length=%i grayscale=%i\n",
+ (int)fb_var->red.offset, (int)fb_var->red.length,
+ (int)fb_var->green.offset, (int)fb_var->green.length,
+ (int)fb_var->blue.offset, (int)fb_var->blue.length,
+ (int)fb_var->transp.offset, (int)fb_var->transp.length,
+ (int)fb_var->grayscale);
+ return PIPE_FORMAT_COUNT;
+ }
+
+ printf("Framebuffer format: %s\n",util_format_short_name(
+ etna_fb_formats[fmt_idx].format));
+
+ return etna_fb_formats[fmt_idx].format;
}
static void *etna_fbdev_create_drawable(struct native_fbdev_screen *fbdev_screen,
@@ -39,7 +107,7 @@ static void *etna_fbdev_create_drawable(struct native_fbdev_screen *fbdev_screen
unsigned xoffset, unsigned yoffset,
unsigned width, unsigned height)
{
- struct etna_rs_target *drawable = CALLOC_STRUCT(etna_rs_target);
+ struct etna_resource *drawable = CALLOC_STRUCT(etna_resource);
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
struct etna_screen *screen = etna_screen(fbdev_screen->screen);
@@ -63,33 +131,36 @@ static void *etna_fbdev_create_drawable(struct native_fbdev_screen *fbdev_screen
height = vinfo.yres_virtual - yoffset;
}
- drawable->width = width;
- drawable->height = height;
+ drawable->base.format = etna_fbdev_get_format(&vinfo);
+ if (drawable->base.format == PIPE_FORMAT_COUNT) {
+ FREE(drawable);
+ return NULL;
+ }
+
drawable->bo = etna_bo_from_fbdev(screen->dev, fd,
finfo.line_length * yoffset + vinfo.bits_per_pixel / 8 * xoffset,
finfo.line_length * height);
- drawable->stride = finfo.line_length;
+ drawable->layout = ETNA_LAYOUT_LINEAR;
+
+ drawable->levels[0].width = width;
+ drawable->levels[0].height = height;
+ drawable->levels[0].padded_width = width;
+ drawable->levels[0].padded_height = height;
+ drawable->levels[0].stride = finfo.line_length;
+
+ drawable->base.screen = fbdev_screen->screen;
+ pipe_reference_init(&drawable->base.reference, 1);
- if(width == 0 || height == 0 ||
- !etna_fb_get_format(&vinfo, &drawable->rs_format, &drawable->swap_rb))
- {
- FREE(drawable);
- return NULL;
- }
return drawable;
}
static void etna_fbdev_destroy_drawable(struct native_fbdev_screen *fbdev_screen, void *hdrawable)
{
- struct etna_rs_target *drawable = (struct etna_rs_target*)hdrawable;
- fbdev_screen->screen->fence_reference(fbdev_screen->screen, &drawable->fence, NULL);
- FREE(drawable);
-}
+ struct etna_resource *drawable = hdrawable;
+ struct etna_screen *screen = etna_screen(fbdev_screen->screen);
-static struct pipe_fence_handle *etna_fbdev_get_drawable_fence(struct native_fbdev_screen *fbdev_screen, void *hdrawable)
-{
- struct etna_rs_target *drawable = (struct etna_rs_target*)hdrawable;
- return (struct pipe_fence_handle*)drawable->fence;
+ etna_bo_del(screen->dev, drawable->bo, NULL);
+ FREE(drawable);
}
static bool etna_fbdev_probe(const struct native_fbdev_driver *driver)
@@ -115,7 +186,7 @@ static struct native_fbdev_screen *etna_fbdev_create_screen(
fscreen->base.destroy = etna_fbdev_screen_destroy;
fscreen->base.create_drawable = etna_fbdev_create_drawable;
fscreen->base.destroy_drawable = etna_fbdev_destroy_drawable;
- fscreen->base.get_drawable_fence = etna_fbdev_get_drawable_fence;
+
return &fscreen->base;
}