1/* 2 * Copyright © 2014 Broadcom 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include <xf86drm.h> 25#include <err.h> 26 27#include "pipe/p_defines.h" 28#include "util/ralloc.h" 29#include "util/u_inlines.h" 30#include "util/u_memory.h" 31#include "util/u_blitter.h" 32#include "util/u_upload_mgr.h" 33#include "indices/u_primconvert.h" 34#include "pipe/p_screen.h" 35 36#include "vc4_screen.h" 37#include "vc4_context.h" 38#include "vc4_resource.h" 39 40void 41vc4_flush(struct pipe_context *pctx) 42{ 43 struct vc4_context *vc4 = vc4_context(pctx); 44 45 hash_table_foreach(vc4->jobs, entry) { 46 struct vc4_job *job = entry->data; 47 vc4_job_submit(vc4, job); 48 } 49} 50 51static void 52vc4_pipe_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence, 53 unsigned flags) 54{ 55 struct vc4_context *vc4 = vc4_context(pctx); 56 57 vc4_flush(pctx); 58 59 if (fence) { 60 struct pipe_screen *screen = pctx->screen; 61 int fd = -1; 62 63 if (flags & PIPE_FLUSH_FENCE_FD) { 64 /* The vc4_fence takes ownership of the returned fd. */ 65 drmSyncobjExportSyncFile(vc4->fd, vc4->job_syncobj, 66 &fd); 67 } 68 69 struct vc4_fence *f = vc4_fence_create(vc4->screen, 70 vc4->last_emit_seqno, 71 fd); 72 screen->fence_reference(screen, fence, NULL); 73 *fence = (struct pipe_fence_handle *)f; 74 } 75} 76 77/* We can't flush the texture cache within rendering a tile, so we have to 78 * flush all rendering to the kernel so that the next job reading from the 79 * tile gets a flushed cache. 80 */ 81static void 82vc4_texture_barrier(struct pipe_context *pctx, unsigned flags) 83{ 84 vc4_flush(pctx); 85} 86 87static void 88vc4_set_debug_callback(struct pipe_context *pctx, 89 const struct pipe_debug_callback *cb) 90{ 91 struct vc4_context *vc4 = vc4_context(pctx); 92 93 if (cb) 94 vc4->debug = *cb; 95 else 96 memset(&vc4->debug, 0, sizeof(vc4->debug)); 97} 98 99static void 100vc4_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc) 101{ 102 struct vc4_context *vc4 = vc4_context(pctx); 103 struct vc4_resource *rsc = vc4_resource(prsc); 104 105 rsc->initialized_buffers = 0; 106 107 struct hash_entry *entry = _mesa_hash_table_search(vc4->write_jobs, 108 prsc); 109 if (!entry) 110 return; 111 112 struct vc4_job *job = entry->data; 113 if (job->key.zsbuf && job->key.zsbuf->texture == prsc) 114 job->resolve &= ~(PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL); 115} 116 117static void 118vc4_context_destroy(struct pipe_context *pctx) 119{ 120 struct vc4_context *vc4 = vc4_context(pctx); 121 122 vc4_flush(pctx); 123 124 if (vc4->blitter) 125 util_blitter_destroy(vc4->blitter); 126 127 if (vc4->primconvert) 128 util_primconvert_destroy(vc4->primconvert); 129 130 if (vc4->uploader) 131 u_upload_destroy(vc4->uploader); 132 133 slab_destroy_child(&vc4->transfer_pool); 134 135 pipe_surface_reference(&vc4->framebuffer.cbufs[0], NULL); 136 pipe_surface_reference(&vc4->framebuffer.zsbuf, NULL); 137 138 if (vc4->yuv_linear_blit_vs) 139 pctx->delete_vs_state(pctx, vc4->yuv_linear_blit_vs); 140 if (vc4->yuv_linear_blit_fs_8bit) 141 pctx->delete_fs_state(pctx, vc4->yuv_linear_blit_fs_8bit); 142 if (vc4->yuv_linear_blit_fs_16bit) 143 pctx->delete_fs_state(pctx, vc4->yuv_linear_blit_fs_16bit); 144 145 vc4_program_fini(pctx); 146 147 if (vc4->screen->has_syncobj) { 148 drmSyncobjDestroy(vc4->fd, vc4->job_syncobj); 149 drmSyncobjDestroy(vc4->fd, vc4->in_syncobj); 150 } 151 if (vc4->in_fence_fd >= 0) 152 close(vc4->in_fence_fd); 153 154 ralloc_free(vc4); 155} 156 157struct pipe_context * 158vc4_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) 159{ 160 struct vc4_screen *screen = vc4_screen(pscreen); 161 struct vc4_context *vc4; 162 int err; 163 164 /* Prevent dumping of the shaders built during context setup. */ 165 uint32_t saved_shaderdb_flag = vc4_debug & VC4_DEBUG_SHADERDB; 166 vc4_debug &= ~VC4_DEBUG_SHADERDB; 167 168 vc4 = rzalloc(NULL, struct vc4_context); 169 if (!vc4) 170 return NULL; 171 struct pipe_context *pctx = &vc4->base; 172 173 vc4->screen = screen; 174 175 pctx->screen = pscreen; 176 pctx->priv = priv; 177 pctx->destroy = vc4_context_destroy; 178 pctx->flush = vc4_pipe_flush; 179 pctx->set_debug_callback = vc4_set_debug_callback; 180 pctx->invalidate_resource = vc4_invalidate_resource; 181 pctx->texture_barrier = vc4_texture_barrier; 182 183 vc4_draw_init(pctx); 184 vc4_state_init(pctx); 185 vc4_program_init(pctx); 186 vc4_query_init(pctx); 187 vc4_resource_context_init(pctx); 188 189 vc4->fd = screen->fd; 190 191 err = vc4_job_init(vc4); 192 if (err) 193 goto fail; 194 195 err = vc4_fence_context_init(vc4); 196 if (err) 197 goto fail; 198 199 slab_create_child(&vc4->transfer_pool, &screen->transfer_pool); 200 201 vc4->uploader = u_upload_create_default(&vc4->base); 202 vc4->base.stream_uploader = vc4->uploader; 203 vc4->base.const_uploader = vc4->uploader; 204 205 vc4->blitter = util_blitter_create(pctx); 206 if (!vc4->blitter) 207 goto fail; 208 209 vc4->primconvert = util_primconvert_create(pctx, 210 (1 << PIPE_PRIM_QUADS) - 1); 211 if (!vc4->primconvert) 212 goto fail; 213 214 vc4_debug |= saved_shaderdb_flag; 215 216 vc4->sample_mask = (1 << VC4_MAX_SAMPLES) - 1; 217 218 return &vc4->base; 219 220fail: 221 pctx->destroy(pctx); 222 return NULL; 223} 224