#include "pan_blending.h"
#include "pan_blend_shaders.h"
#include "pan_util.h"
-#include "pan_wallpaper.h"
static int performance_counter_number = 0;
extern const char *pan_counters_base;
#endif
}
+static void
+panfrost_draw_wallpaper(struct pipe_context *pipe)
+{
+ struct panfrost_context *ctx = pan_context(pipe);
+ struct pipe_blit_info binfo = { };
+
+ /* Nothing to reload? */
+ if (ctx->pipe_framebuffer.cbufs[0] == NULL)
+ return;
+
+ util_blitter_save_vertex_buffer_slot(ctx->blitter, ctx->vertex_buffers);
+ util_blitter_save_vertex_elements(ctx->blitter, ctx->vertex);
+ util_blitter_save_vertex_shader(ctx->blitter, ctx->vs);
+ util_blitter_save_rasterizer(ctx->blitter, ctx->rasterizer);
+ util_blitter_save_viewport(ctx->blitter, &ctx->pipe_viewport);
+ util_blitter_save_scissor(ctx->blitter, &ctx->scissor);
+ util_blitter_save_fragment_shader(ctx->blitter, ctx->fs);
+ util_blitter_save_blend(ctx->blitter, ctx->blend);
+ util_blitter_save_depth_stencil_alpha(ctx->blitter, ctx->depth_stencil);
+ util_blitter_save_stencil_ref(ctx->blitter, &ctx->stencil_ref);
+ util_blitter_save_so_targets(ctx->blitter, 0, NULL);
+
+ /* For later */
+// util_blitter_save_sample_mask(ctx->blitter, vc4->sample_mask);
+
+ util_blitter_save_framebuffer(ctx->blitter, &ctx->pipe_framebuffer);
+ util_blitter_save_fragment_sampler_states(ctx->blitter,
+ ctx->sampler_count[PIPE_SHADER_FRAGMENT],
+ (void **)(&ctx->samplers[PIPE_SHADER_FRAGMENT]));
+ util_blitter_save_fragment_sampler_views(ctx->blitter,
+ ctx->sampler_view_count[PIPE_SHADER_FRAGMENT],
+ (struct pipe_sampler_view **)&ctx->sampler_views[PIPE_SHADER_FRAGMENT]);
+
+
+ binfo.src.resource = binfo.dst.resource = ctx->pipe_framebuffer.cbufs[0]->texture;
+ binfo.src.level = binfo.dst.level = 0;
+ binfo.src.box.x = binfo.dst.box.x = 0;
+ binfo.src.box.y = binfo.dst.box.y = 0;
+ binfo.src.box.width = binfo.dst.box.width = ctx->pipe_framebuffer.width;
+ binfo.src.box.height = binfo.dst.box.height = ctx->pipe_framebuffer.height;
+
+ /* This avoids an assert due to missing nir_texop_txb support */
+ //binfo.src.box.depth = binfo.dst.box.depth = 1;
+
+ binfo.src.format = binfo.dst.format = ctx->pipe_framebuffer.cbufs[0]->texture->format;
+
+ assert(ctx->pipe_framebuffer.nr_cbufs == 1);
+ binfo.mask = PIPE_MASK_RGBA;
+ binfo.filter = PIPE_TEX_FILTER_LINEAR;
+ binfo.scissor_enable = FALSE;
+
+ util_blitter_blit(ctx->blitter, &binfo);
+
+ /* We are flushing all queued draws and we know that no more jobs will
+ * be added until the next frame.
+ * We also know that the last jobs are the wallpaper jobs, and they
+ * need to be linked so they execute right after the set_value job.
+ */
+
+ /* set_value job to wallpaper vertex job */
+ panfrost_link_job_pair(ctx->u_set_value_job, ctx->vertex_jobs[ctx->vertex_job_count - 1]);
+ ctx->u_vertex_jobs[ctx->vertex_job_count - 1]->job_dependency_index_1 = ctx->u_set_value_job->job_index;
+
+ /* wallpaper vertex job to first vertex job */
+ panfrost_link_job_pair(ctx->u_vertex_jobs[ctx->vertex_job_count - 1], ctx->vertex_jobs[0]);
+ ctx->u_vertex_jobs[0]->job_dependency_index_1 = ctx->u_set_value_job->job_index;
+
+ /* last vertex job to wallpaper tiler job */
+ panfrost_link_job_pair(ctx->u_vertex_jobs[ctx->vertex_job_count - 2], ctx->tiler_jobs[ctx->tiler_job_count - 1]);
+ ctx->u_tiler_jobs[ctx->tiler_job_count - 1]->job_dependency_index_1 = ctx->u_vertex_jobs[ctx->vertex_job_count - 1]->job_index;
+ ctx->u_tiler_jobs[ctx->tiler_job_count - 1]->job_dependency_index_2 = 0;
+
+ /* wallpaper tiler job to first tiler job */
+ panfrost_link_job_pair(ctx->u_tiler_jobs[ctx->tiler_job_count - 1], ctx->tiler_jobs[0]);
+ ctx->u_tiler_jobs[0]->job_dependency_index_1 = ctx->u_vertex_jobs[0]->job_index;
+ ctx->u_tiler_jobs[0]->job_dependency_index_2 = ctx->u_tiler_jobs[ctx->tiler_job_count - 1]->job_index;
+
+ /* last tiler job to NULL */
+ panfrost_link_job_pair(ctx->u_tiler_jobs[ctx->tiler_job_count - 2], 0);
+}
+
void
panfrost_flush(
struct pipe_context *pipe,
/* Nothing to do! */
if (!ctx->draw_count && !job->clear) return;
+ if (!job->clear)
+ panfrost_draw_wallpaper(&ctx->base);
+
/* Whether to stall the pipeline for immediately correct results */
bool flush_immediate = flags & PIPE_FLUSH_END_OF_FRAME;
{
struct panfrost_context *ctx = pan_context(pctx);
- /* Flush when switching away from an FBO */
+ /* Flush when switching away from an FBO, but not if the framebuffer
+ * state is being restored by u_blitter
+ */
- if (!panfrost_is_scanout(ctx)) {
+ if (!panfrost_is_scanout(ctx) && !ctx->blitter->running) {
panfrost_flush(pctx, NULL, 0);
}
+++ /dev/null
-/*
- * © Copyright 2018 Alyssa Rosenzweig
- *
- * 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 "pan_wallpaper.h"
-#include "pan_context.h"
-#include "pan_screen.h"
-#include "pan_util.h"
-//#include "include/panfrost-job.h"
-#include "midgard/midgard_compile.h"
-#include "compiler/nir/nir_builder.h"
-
-/* Creates the special-purpose fragment shader for wallpapering. A
- * pseudo-vertex shader sets us up for a fullscreen quad render, with a texture
- * coordinate varying */
-
-static nir_shader *
-panfrost_build_wallpaper_program()
-{
- nir_shader *shader = nir_shader_create(NULL, MESA_SHADER_FRAGMENT, &midgard_nir_options, NULL);
- nir_function *fn = nir_function_create(shader, "main");
- nir_function_impl *impl = nir_function_impl_create(fn);
-
- /* Create the variables variables */
-
- nir_variable *c_texcoord = nir_variable_create(shader, nir_var_shader_in, glsl_vector_type(GLSL_TYPE_FLOAT, 4), "gl_TexCoord");
- nir_variable *c_out = nir_variable_create(shader, nir_var_shader_out, glsl_vector_type(GLSL_TYPE_FLOAT, 4), "gl_FragColor");
-
- c_texcoord->data.location = VARYING_SLOT_VAR0;
- c_out->data.location = FRAG_RESULT_COLOR;
-
- /* Setup nir_builder */
-
- nir_builder _b;
- nir_builder *b = &_b;
- nir_builder_init(b, impl);
- b->cursor = nir_before_block(nir_start_block(impl));
-
- /* Setup inputs */
-
- nir_ssa_def *s_src = nir_load_var(b, c_texcoord);
-
- /* Build the passthrough texture shader */
-
- nir_tex_instr *tx = nir_tex_instr_create(shader, 1);
- tx->op = nir_texop_tex;
- tx->texture_index = tx->sampler_index = 0;
- tx->sampler_dim = GLSL_SAMPLER_DIM_2D;
- tx->dest_type = nir_type_float;
-
- nir_src src = nir_src_for_ssa(s_src);
- nir_src_copy(&tx->src[0].src, &src, tx);
- tx->src[0].src_type = nir_tex_src_coord;
-
- nir_ssa_dest_init(&tx->instr, &tx->dest, nir_tex_instr_dest_size(tx), 32, NULL);
- nir_builder_instr_insert(b, &tx->instr);
-
- nir_ssa_def *texel = &tx->dest.ssa;
-
- nir_store_var(b, c_out, texel, 0xFF);
-
- return shader;
-}
-
-/* Creates the CSO corresponding to the wallpaper program */
-
-static struct panfrost_shader_variants *
-panfrost_create_wallpaper_program(struct pipe_context *pctx)
-{
- nir_shader *built_nir_shader = panfrost_build_wallpaper_program();
-
- struct pipe_shader_state so = {
- .type = PIPE_SHADER_IR_NIR,
- .ir = {
- .nir = built_nir_shader
- }
- };
-
- return pctx->create_fs_state(pctx, &so);
-}
-
-static struct panfrost_shader_variants *wallpaper_program = NULL;
-static struct panfrost_shader_variants *wallpaper_saved_program = NULL;
-
-static void
-panfrost_enable_wallpaper_program(struct pipe_context *pctx)
-{
- struct panfrost_context *ctx = pan_context(pctx);
-
- if (!wallpaper_program) {
- wallpaper_program = panfrost_create_wallpaper_program(pctx);
- }
-
- /* Push the shader state */
- wallpaper_saved_program = ctx->fs;
-
- /* Bind the program */
- pctx->bind_fs_state(pctx, wallpaper_program);
-}
-
-static void
-panfrost_disable_wallpaper_program(struct pipe_context *pctx)
-{
- /* Pop off the shader state */
- pctx->bind_fs_state(pctx, wallpaper_saved_program);
-}
-
-/* Essentially, we insert a fullscreen textured quad, reading from the
- * previous frame's framebuffer */
-
-void
-panfrost_draw_wallpaper(struct pipe_context *pipe)
-{
- /* Disable wallpapering for now, but still exercise the shader generation to minimise bit rot */
-
- panfrost_enable_wallpaper_program(pipe);
- panfrost_disable_wallpaper_program(pipe);
-
- return;
-
-#if 0
- struct panfrost_context *ctx = pan_context(pipe);
-
- /* Setup payload for elided quad. TODO: Refactor draw_vbo so this can
- * be a little more DRY */
-
- ctx->payload_tiler.draw_start = 0;
- ctx->payload_tiler.prefix.draw_mode = MALI_TRIANGLE_STRIP;
- ctx->vertex_count = 4;
- ctx->payload_tiler.prefix.invocation_count = MALI_POSITIVE(4);
- ctx->payload_tiler.prefix.unknown_draw &= ~(0x3000 | 0x18000);
- ctx->payload_tiler.prefix.unknown_draw |= 0x18000;
- ctx->payload_tiler.prefix.negative_start = 0;
- ctx->payload_tiler.prefix.index_count = MALI_POSITIVE(4);
- ctx->payload_tiler.prefix.unknown_draw &= ~MALI_DRAW_INDEXED_UINT32;
- ctx->payload_tiler.prefix.indices = (uintptr_t) NULL;
-
- /* Setup the wallpapering program. We need to build the program via
- * NIR. */
-
- panfrost_enable_wallpaper_program(pipe);
-
- /* Setup the texture/sampler pair */
-
- struct pipe_sampler_view tmpl = {
- .target = PIPE_TEXTURE_2D,
- .swizzle_r = PIPE_SWIZZLE_X,
- .swizzle_g = PIPE_SWIZZLE_Y,
- .swizzle_b = PIPE_SWIZZLE_Z,
- .swizzle_a = PIPE_SWIZZLE_W
- };
-
- struct pipe_sampler_state state = {
- .min_mip_filter = PIPE_TEX_MIPFILTER_NONE,
- .min_img_filter = PIPE_TEX_MIPFILTER_LINEAR,
- .mag_img_filter = PIPE_TEX_MIPFILTER_LINEAR,
- .wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE,
- .wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE,
- .wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE,
- .normalized_coords = 1
- };
-
- struct pipe_resource *rsrc = pan_screen(pipe->screen)->display_target;
- struct pipe_sampler_state *sampler_state = pipe->create_sampler_state(pipe, &state);
- struct pipe_sampler_view *sampler_view = pipe->create_sampler_view(pipe, rsrc, &tmpl);
-
- /* Bind texture/sampler. TODO: push/pop */
- pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0, 1, &sampler_state);
- pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 1, &sampler_view);
-
- panfrost_emit_for_draw(ctx, false);
-
- /* Elision occurs by essential precomputing the results of the
- * implied vertex shader. Insert these results for fullscreen. The
- * first two channels are ~screenspace coordinates, whereas the latter
- * two are fixed 0.0/1.0 after perspective division. See the vertex
- * shader epilogue for more context */
-
- float implied_position_varying[] = {
- /* The following is correct for scissored clears whose scissor deals with cutoff appropriately */
-
-// -1.0, -1.0, 0.0, 1.0,
-// -1.0, 65535.0, 0.0, 1.0,
-// 65536.0, 1.0, 0.0, 1.0,
-// 65536.0, 65536.0, 0.0, 1.0
-
- /* The following output is correct for a fullscreen quad with screen size 2048x1600 */
- 0.0, 0.0, 0.0, 1.0,
- 0.0, 1600.0, 0.0, 1.0,
- 2048.0, 0.0, 0.0, 1.0,
- 2048.0, 1280.0, 0.0, 1.0,
- };
-
- ctx->payload_tiler.postfix.position_varying = panfrost_upload_transient(ctx, implied_position_varying, sizeof(implied_position_varying));
-
- /* Similarly, setup the texture coordinate varying, hardcoded to match
- * the corners of the screen */
-
- float texture_coordinates[] = {
- 0.0, 0.0, 0.0, 0.0,
- 0.0, 1.0, 0.0, 0.0,
- 1.0, 0.0, 0.0, 0.0,
- 1.0, 1.0, 0.0, 0.0
- };
-
- union mali_attr varyings[1] = {
- {
- .elements = panfrost_upload_transient(ctx, texture_coordinates, sizeof(texture_coordinates)) | 1,
- .stride = sizeof(float) * 4,
- .size = sizeof(texture_coordinates)
- }
- };
-
- ctx->payload_tiler.postfix.varyings = panfrost_upload_transient(ctx, varyings, sizeof(varyings));
-
- struct mali_attr_meta varying_meta[1] = {
- {
- .type = MALI_ATYPE_FLOAT,
- .nr_components = MALI_POSITIVE(4),
- .not_normalised = 1,
- .unknown1 = /*0x2c22 - nr_comp=2*/ 0x2a22,
- .unknown2 = 0x1
- }
- };
-
- mali_ptr saved_varying_meta = ctx->payload_tiler.postfix.varying_meta;
- ctx->payload_tiler.postfix.varying_meta = panfrost_upload_transient(ctx, varying_meta, sizeof(varying_meta));
-
- /* Emit the tiler job */
- struct panfrost_transfer tiler = panfrost_vertex_tiler_job(ctx, true, true);
- struct mali_job_descriptor_header *jd = (struct mali_job_descriptor_header *) tiler.cpu;
- ctx->u_tiler_jobs[ctx->tiler_job_count] = jd;
- ctx->tiler_jobs[ctx->tiler_job_count++] = tiler.gpu;
- ctx->draw_count++;
-
- /* Okay, so we have the tiler job emitted. Since we set elided_tiler
- * mode, no dependencies will be set automatically. We don't actually
- * want any dependencies, since we go first and we don't need a vertex
- * first. That said, we do need the first tiler job to depend on us.
- * Its second dep slot will be free (see the panfrost_vertex_tiler_job
- * dependency setting algorithm), so fill us in with that
- */
-
- if (ctx->tiler_job_count > 1) {
- ctx->u_tiler_jobs[0]->job_dependency_index_2 = jd->job_index;
- }
-
- printf("Wallpaper boop\n");
-
- /* Cleanup */
- panfrost_disable_wallpaper_program(pipe);
- ctx->payload_tiler.postfix.varying_meta = saved_varying_meta;
-#endif
-}