diff options
Diffstat (limited to 'src/gallium/drivers/vc4/vc4_draw.c')
-rw-r--r-- | src/gallium/drivers/vc4/vc4_draw.c | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/src/gallium/drivers/vc4/vc4_draw.c b/src/gallium/drivers/vc4/vc4_draw.c new file mode 100644 index 00000000000..4c25dabae7d --- /dev/null +++ b/src/gallium/drivers/vc4/vc4_draw.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2014 Scott Mansell + * Copyright © 2014 Broadcom + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <stdio.h> + +#include "vc4_context.h" +#include "vc4_resource.h" + +static struct vc4_bo * +get_vbo(struct vc4_context *vc4, uint32_t width, uint32_t height) +{ + struct { + uint16_t x, y; + float z, rhw, r, g, b; + } verts[] = { + { + // Vertex: Top, red + (-(int)width / 3) << 4, // X in 12.4 fixed point + (-(int)height / 3) << 4, // Y in 12.4 fixed point + 1.0f, // Z + 1.0f, // 1/W + 1.0f, // Varying 0 (Red) + 0.0f, // Varying 1 (Green) + 0.0f, // Varying 2 (Blue) + }, + { + // Vertex: bottom left, Green + (width / 3) << 4, // X in 12.4 fixed point + (-(int)height / 3) << 4, // Y in 12.4 fixed point + 1.0f, // Z + 1.0f, // 1/W + 0.0f, // Varying 0 (Red) + 1.0f, // Varying 1 (Green) + 0.0f, // Varying 2 (Blue) + }, + + { + // Vertex: bottom right, Blue + (width / 3) << 4, // X in 12.4 fixed point + (height / 3) << 4, // Y in 12.4 fixed point + 1.0f, // Z + 1.0f, // 1/W + 0.0f, // Varying 0 (Red) + 0.0f, // Varying 1 (Green) + 1.0f, // Varying 2 (Blue) + }, + }; + + return vc4_bo_alloc_mem(vc4->screen, verts, sizeof(verts), "verts"); +} +static struct vc4_bo * +get_ibo(struct vc4_context *vc4) +{ + static const uint8_t indices[] = { 0, 1, 2 }; + + return vc4_bo_alloc_mem(vc4->screen, indices, sizeof(indices), "indices"); +} + +static void +vc4_rcl_tile_calls(struct vc4_context *vc4, + uint32_t xtiles, uint32_t ytiles, + struct vc4_bo *tile_alloc) +{ + for (int x = 0; x < xtiles; x++) { + for (int y = 0; y < ytiles; y++) { + cl_u8(&vc4->rcl, VC4_PACKET_TILE_COORDINATES); + cl_u8(&vc4->rcl, x); + cl_u8(&vc4->rcl, y); + + cl_start_reloc(&vc4->rcl, 1); + cl_u8(&vc4->rcl, VC4_PACKET_BRANCH_TO_SUB_LIST); + cl_reloc(vc4, &vc4->rcl, tile_alloc, + (y * xtiles + x) * 32); + + if (x == xtiles - 1 && y == ytiles - 1) { + cl_u8(&vc4->rcl, + VC4_PACKET_STORE_MS_TILE_BUFFER_AND_EOF); + } else { + cl_u8(&vc4->rcl, + VC4_PACKET_STORE_MS_TILE_BUFFER); + } + } + } +} + +static void +vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) +{ + struct vc4_context *vc4 = vc4_context(pctx); + uint32_t width = vc4->framebuffer.width; + uint32_t height = vc4->framebuffer.height; + uint32_t tilew = align(width, 64) / 64; + uint32_t tileh = align(height, 64) / 64; + struct vc4_bo *tile_alloc = vc4_bo_alloc(vc4->screen, + 32 * tilew * tileh, "tilea"); + struct vc4_bo *tile_state = vc4_bo_alloc(vc4->screen, + 48 * tilew * tileh, "tilestate"); + struct vc4_bo *ibo = get_ibo(vc4); + + struct vc4_bo *fs_uniform = vc4_bo_alloc(vc4->screen, 0x1000, "fsu"); + struct vc4_bo *vbo = get_vbo(vc4, width, height); + + vc4->needs_flush = true; + + // Tile state data is 48 bytes per tile, I think it can be thrown away + // as soon as binning is finished. + cl_start_reloc(&vc4->bcl, 2); + cl_u8(&vc4->bcl, VC4_PACKET_TILE_BINNING_MODE_CONFIG); + cl_reloc(vc4, &vc4->bcl, tile_alloc, 0); + cl_u32(&vc4->bcl, 0x8000); /* tile allocation memory size */ + cl_reloc(vc4, &vc4->bcl, tile_state, 0); + cl_u8(&vc4->bcl, tilew); + cl_u8(&vc4->bcl, tileh); + cl_u8(&vc4->bcl, VC4_BIN_CONFIG_AUTO_INIT_TSDA); + + cl_u8(&vc4->bcl, VC4_PACKET_START_TILE_BINNING); + + cl_u8(&vc4->bcl, VC4_PACKET_PRIMITIVE_LIST_FORMAT); + cl_u8(&vc4->bcl, 0x32); // 16 bit triangle + + vc4_emit_state(pctx); + + /* the actual draw call. */ + cl_u8(&vc4->bcl, VC4_PACKET_NV_SHADER_STATE); +#ifndef USE_VC4_SIMULATOR + cl_u32(&vc4->bcl, 0); /* offset into shader_rec */ +#else + cl_u32(&vc4->bcl, simpenrose_hw_addr(vc4->shader_rec.next)); +#endif + + cl_start_reloc(&vc4->bcl, 1); + cl_u8(&vc4->bcl, VC4_PACKET_GL_INDEXED_PRIMITIVE); + cl_u8(&vc4->bcl, 0x04); // 8bit index, trinagles + cl_u32(&vc4->bcl, 3); // Length + cl_reloc(vc4, &vc4->bcl, ibo, 0); + cl_u32(&vc4->bcl, 2); // Maximum index + + cl_u8(&vc4->bcl, VC4_PACKET_FLUSH_ALL); + cl_u8(&vc4->bcl, VC4_PACKET_NOP); + cl_u8(&vc4->bcl, VC4_PACKET_HALT); + +// Shader Record + cl_start_shader_reloc(&vc4->shader_rec, 3); + + cl_u8(&vc4->shader_rec, 0); + cl_u8(&vc4->shader_rec, 6*4); // stride + cl_u8(&vc4->shader_rec, 0xcc); // num uniforms (not used) + cl_u8(&vc4->shader_rec, 3); // num varyings + cl_reloc(vc4, &vc4->shader_rec, vc4->prog.fs->bo, 0); + cl_reloc(vc4, &vc4->shader_rec, fs_uniform, 0); + cl_reloc(vc4, &vc4->shader_rec, vbo, 0); + + vc4->shader_rec_count++; + + cl_u8(&vc4->rcl, VC4_PACKET_CLEAR_COLORS); + cl_u32(&vc4->rcl, 0xff000000); // Opaque Black + cl_u32(&vc4->rcl, 0xff000000); // 32 bit clear colours need to be repeated twice + cl_u32(&vc4->rcl, 0); + cl_u8(&vc4->rcl, 0); + + struct vc4_surface *csurf = vc4_surface(vc4->framebuffer.cbufs[0]); + struct vc4_resource *ctex = vc4_resource(csurf->base.texture); + + cl_start_reloc(&vc4->rcl, 1); + cl_u8(&vc4->rcl, VC4_PACKET_TILE_RENDERING_MODE_CONFIG); + cl_reloc(vc4, &vc4->rcl, ctex->bo, csurf->offset); + cl_u16(&vc4->rcl, width); + cl_u16(&vc4->rcl, height); + cl_u8(&vc4->rcl, (VC4_RENDER_CONFIG_MEMORY_FORMAT_LINEAR | + VC4_RENDER_CONFIG_FORMAT_RGBA8888)); + cl_u8(&vc4->rcl, 0); + + // Do a store of the first tile to force the tile buffer to be cleared + /* XXX: I think these two packets may be unnecessary. */ + cl_u8(&vc4->rcl, VC4_PACKET_TILE_COORDINATES); + cl_u8(&vc4->rcl, 0); + cl_u8(&vc4->rcl, 0); + + cl_u8(&vc4->rcl, VC4_PACKET_STORE_TILE_BUFFER_GENERAL); + cl_u16(&vc4->rcl, 0); // Store nothing (just clear) + cl_u32(&vc4->rcl, 0); // no address is needed + + vc4_rcl_tile_calls(vc4, tilew, tileh, tile_alloc); + + vc4_flush(pctx); +} + +static void +vc4_clear(struct pipe_context *pctx, unsigned buffers, + const union pipe_color_union *color, double depth, unsigned stencil) +{ + struct vc4_context *vc4 = vc4_context(pctx); + + vc4->needs_flush = true; +} + +static void +vc4_clear_render_target(struct pipe_context *pctx, struct pipe_surface *ps, + const union pipe_color_union *color, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + fprintf(stderr, "unimpl: clear RT\n"); +} + +static void +vc4_clear_depth_stencil(struct pipe_context *pctx, struct pipe_surface *ps, + unsigned buffers, double depth, unsigned stencil, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + fprintf(stderr, "unimpl: clear DS\n"); +} + +void +vc4_draw_init(struct pipe_context *pctx) +{ + pctx->draw_vbo = vc4_draw_vbo; + pctx->clear = vc4_clear; + pctx->clear_render_target = vc4_clear_render_target; + pctx->clear_depth_stencil = vc4_clear_depth_stencil; +} |