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 "pipe/p_screen.h" 34 35#include "vc4_screen.h" 36#include "vc4_context.h" 37#include "vc4_resource.h" 38 39void 40vc4_flush(struct pipe_context *pctx) 41{ 42 struct vc4_context *vc4 = vc4_context(pctx); 43 44 hash_table_foreach(vc4->jobs, entry) { 45 struct vc4_job *job = entry->data; 46 vc4_job_submit(vc4, job); 47 } 48} 49 50static void 51vc4_pipe_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence, 52 unsigned flags) 53{ 54 struct vc4_context *vc4 = vc4_context(pctx); 55 56 vc4_flush(pctx); 57 58 if (fence) { 59 struct pipe_screen *screen = pctx->screen; 60 int fd = -1; 61 62 if (flags & PIPE_FLUSH_FENCE_FD) { 63 /* The vc4_fence takes ownership of the returned fd. */ 64 drmSyncobjExportSyncFile(vc4->fd, vc4->job_syncobj, 65 &fd); 66 } 67 68 struct vc4_fence *f = vc4_fence_create(vc4->screen, 69 vc4->last_emit_seqno, 70 fd); 71 screen->fence_reference(screen, fence, NULL); 72 *fence = (struct pipe_fence_handle *)f; 73 } 74} 75 76/* We can't flush the texture cache within rendering a tile, so we have to 77 * flush all rendering to the kernel so that the next job reading from the 78 * tile gets a flushed cache. 79 */ 80static void 81vc4_texture_barrier(struct pipe_context *pctx, unsigned flags) 82{ 83 vc4_flush(pctx); 84} 85 86static void 87vc4_set_debug_callback(struct pipe_context *pctx, 88 const struct util_debug_callback *cb) 89{ 90 struct vc4_context *vc4 = vc4_context(pctx); 91 92 if (cb) 93 vc4->debug = *cb; 94 else 95 memset(&vc4->debug, 0, sizeof(vc4->debug)); 96} 97 98static void 99vc4_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc) 100{ 101 struct vc4_context *vc4 = vc4_context(pctx); 102 struct vc4_resource *rsc = vc4_resource(prsc); 103 104 rsc->initialized_buffers = 0; 105 106 struct hash_entry *entry = _mesa_hash_table_search(vc4->write_jobs, 107 prsc); 108 if (!entry) 109 return; 110 111 struct vc4_job *job = entry->data; 112 if (job->key.zsbuf && job->key.zsbuf->texture == prsc) 113 job->resolve &= ~(PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL); 114} 115 116static void 117vc4_context_destroy(struct pipe_context *pctx) 118{ 119 struct vc4_context *vc4 = vc4_context(pctx); 120 121 vc4_flush(pctx); 122 123 if (vc4->blitter) 124 util_blitter_destroy(vc4->blitter); 125 126 if (vc4->uploader) 127 u_upload_destroy(vc4->uploader); 128 129 slab_destroy_child(&vc4->transfer_pool); 130 131 pipe_surface_reference(&vc4->framebuffer.cbufs[0], NULL); 132 pipe_surface_reference(&vc4->framebuffer.zsbuf, NULL); 133 134 if (vc4->yuv_linear_blit_vs) 135 pctx->delete_vs_state(pctx, vc4->yuv_linear_blit_vs); 136 if (vc4->yuv_linear_blit_fs_8bit) 137 pctx->delete_fs_state(pctx, vc4->yuv_linear_blit_fs_8bit); 138 if (vc4->yuv_linear_blit_fs_16bit) 139 pctx->delete_fs_state(pctx, vc4->yuv_linear_blit_fs_16bit); 140 141 vc4_program_fini(pctx); 142 143 if (vc4->screen->has_syncobj) { 144 drmSyncobjDestroy(vc4->fd, vc4->job_syncobj); 145 drmSyncobjDestroy(vc4->fd, vc4->in_syncobj); 146 } 147 if (vc4->in_fence_fd >= 0) 148 close(vc4->in_fence_fd); 149 150 ralloc_free(vc4); 151} 152 153struct pipe_context * 154vc4_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) 155{ 156 struct vc4_screen *screen = vc4_screen(pscreen); 157 struct vc4_context *vc4; 158 int err; 159 160 /* Prevent dumping of the shaders built during context setup. */ 161 uint32_t saved_shaderdb_flag = vc4_debug & VC4_DEBUG_SHADERDB; 162 vc4_debug &= ~VC4_DEBUG_SHADERDB; 163 164 vc4 = rzalloc(NULL, struct vc4_context); 165 if (!vc4) 166 return NULL; 167 struct pipe_context *pctx = &vc4->base; 168 169 vc4->screen = screen; 170 171 pctx->screen = pscreen; 172 pctx->priv = priv; 173 pctx->destroy = vc4_context_destroy; 174 pctx->flush = vc4_pipe_flush; 175 pctx->set_debug_callback = vc4_set_debug_callback; 176 pctx->invalidate_resource = vc4_invalidate_resource; 177 pctx->texture_barrier = vc4_texture_barrier; 178 179 vc4_draw_init(pctx); 180 vc4_state_init(pctx); 181 vc4_program_init(pctx); 182 vc4_query_init(pctx); 183 vc4_resource_context_init(pctx); 184 185 vc4->fd = screen->fd; 186 187 err = vc4_job_init(vc4); 188 if (err) 189 goto fail; 190 191 err = vc4_fence_context_init(vc4); 192 if (err) 193 goto fail; 194 195 slab_create_child(&vc4->transfer_pool, &screen->transfer_pool); 196 197 vc4->uploader = u_upload_create_default(&vc4->base); 198 vc4->base.stream_uploader = vc4->uploader; 199 vc4->base.const_uploader = vc4->uploader; 200 201 vc4->blitter = util_blitter_create(pctx); 202 if (!vc4->blitter) 203 goto fail; 204 205 vc4_debug |= saved_shaderdb_flag; 206 207 vc4->sample_mask = (1 << VC4_MAX_SAMPLES) - 1; 208 209 return &vc4->base; 210 211fail: 212 pctx->destroy(pctx); 213 return NULL; 214} 215