1b8e80941Smrg/* 2b8e80941Smrg * Copyright © 2014-2017 Broadcom 3b8e80941Smrg * 4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5b8e80941Smrg * copy of this software and associated documentation files (the "Software"), 6b8e80941Smrg * to deal in the Software without restriction, including without limitation 7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the 9b8e80941Smrg * Software is furnished to do so, subject to the following conditions: 10b8e80941Smrg * 11b8e80941Smrg * The above copyright notice and this permission notice (including the next 12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the 13b8e80941Smrg * Software. 14b8e80941Smrg * 15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21b8e80941Smrg * IN THE SOFTWARE. 22b8e80941Smrg */ 23b8e80941Smrg 24b8e80941Smrg#include <xf86drm.h> 25b8e80941Smrg#include <err.h> 26b8e80941Smrg 27b8e80941Smrg#include "pipe/p_defines.h" 28b8e80941Smrg#include "util/hash_table.h" 29b8e80941Smrg#include "util/ralloc.h" 30b8e80941Smrg#include "util/u_inlines.h" 31b8e80941Smrg#include "util/u_memory.h" 32b8e80941Smrg#include "util/u_blitter.h" 33b8e80941Smrg#include "util/u_upload_mgr.h" 34b8e80941Smrg#include "indices/u_primconvert.h" 35b8e80941Smrg#include "pipe/p_screen.h" 36b8e80941Smrg 37b8e80941Smrg#include "v3d_screen.h" 38b8e80941Smrg#include "v3d_context.h" 39b8e80941Smrg#include "v3d_resource.h" 40b8e80941Smrg#include "broadcom/compiler/v3d_compiler.h" 41b8e80941Smrg 42b8e80941Smrgvoid 43b8e80941Smrgv3d_flush(struct pipe_context *pctx) 44b8e80941Smrg{ 45b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 46b8e80941Smrg 47b8e80941Smrg hash_table_foreach(v3d->jobs, entry) { 48b8e80941Smrg struct v3d_job *job = entry->data; 49b8e80941Smrg v3d_job_submit(v3d, job); 50b8e80941Smrg } 51b8e80941Smrg} 52b8e80941Smrg 53b8e80941Smrgstatic void 54b8e80941Smrgv3d_pipe_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence, 55b8e80941Smrg unsigned flags) 56b8e80941Smrg{ 57b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 58b8e80941Smrg 59b8e80941Smrg v3d_flush(pctx); 60b8e80941Smrg 61b8e80941Smrg if (fence) { 62b8e80941Smrg struct pipe_screen *screen = pctx->screen; 63b8e80941Smrg struct v3d_fence *f = v3d_fence_create(v3d); 64b8e80941Smrg screen->fence_reference(screen, fence, NULL); 65b8e80941Smrg *fence = (struct pipe_fence_handle *)f; 66b8e80941Smrg } 67b8e80941Smrg} 68b8e80941Smrg 69b8e80941Smrgstatic void 70b8e80941Smrgv3d_memory_barrier(struct pipe_context *pctx, unsigned int flags) 71b8e80941Smrg{ 72b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 73b8e80941Smrg 74b8e80941Smrg if (!(flags & ~PIPE_BARRIER_UPDATE)) 75b8e80941Smrg return; 76b8e80941Smrg 77b8e80941Smrg /* We only need to flush jobs writing to SSBOs/images. */ 78b8e80941Smrg perf_debug("Flushing all jobs for glMemoryBarrier(), could do better"); 79b8e80941Smrg v3d_flush(pctx); 80b8e80941Smrg} 81b8e80941Smrg 82b8e80941Smrgstatic void 83b8e80941Smrgv3d_set_debug_callback(struct pipe_context *pctx, 84b8e80941Smrg const struct pipe_debug_callback *cb) 85b8e80941Smrg{ 86b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 87b8e80941Smrg 88b8e80941Smrg if (cb) 89b8e80941Smrg v3d->debug = *cb; 90b8e80941Smrg else 91b8e80941Smrg memset(&v3d->debug, 0, sizeof(v3d->debug)); 92b8e80941Smrg} 93b8e80941Smrg 94b8e80941Smrgstatic void 95b8e80941Smrgv3d_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc) 96b8e80941Smrg{ 97b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 98b8e80941Smrg struct v3d_resource *rsc = v3d_resource(prsc); 99b8e80941Smrg 100b8e80941Smrg rsc->initialized_buffers = 0; 101b8e80941Smrg 102b8e80941Smrg struct hash_entry *entry = _mesa_hash_table_search(v3d->write_jobs, 103b8e80941Smrg prsc); 104b8e80941Smrg if (!entry) 105b8e80941Smrg return; 106b8e80941Smrg 107b8e80941Smrg struct v3d_job *job = entry->data; 108b8e80941Smrg if (job->key.zsbuf && job->key.zsbuf->texture == prsc) 109b8e80941Smrg job->store &= ~(PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL); 110b8e80941Smrg} 111b8e80941Smrg 112b8e80941Smrgstatic void 113b8e80941Smrgv3d_context_destroy(struct pipe_context *pctx) 114b8e80941Smrg{ 115b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 116b8e80941Smrg 117b8e80941Smrg v3d_flush(pctx); 118b8e80941Smrg 119b8e80941Smrg if (v3d->blitter) 120b8e80941Smrg util_blitter_destroy(v3d->blitter); 121b8e80941Smrg 122b8e80941Smrg if (v3d->primconvert) 123b8e80941Smrg util_primconvert_destroy(v3d->primconvert); 124b8e80941Smrg 125b8e80941Smrg if (v3d->uploader) 126b8e80941Smrg u_upload_destroy(v3d->uploader); 127b8e80941Smrg if (v3d->state_uploader) 128b8e80941Smrg u_upload_destroy(v3d->state_uploader); 129b8e80941Smrg 130b8e80941Smrg slab_destroy_child(&v3d->transfer_pool); 131b8e80941Smrg 132b8e80941Smrg pipe_surface_reference(&v3d->framebuffer.cbufs[0], NULL); 133b8e80941Smrg pipe_surface_reference(&v3d->framebuffer.zsbuf, NULL); 134b8e80941Smrg 135b8e80941Smrg v3d_program_fini(pctx); 136b8e80941Smrg 137b8e80941Smrg ralloc_free(v3d); 138b8e80941Smrg} 139b8e80941Smrg 140b8e80941Smrgstatic void 141b8e80941Smrgv3d_get_sample_position(struct pipe_context *pctx, 142b8e80941Smrg unsigned sample_count, unsigned sample_index, 143b8e80941Smrg float *xy) 144b8e80941Smrg{ 145b8e80941Smrg struct v3d_context *v3d = v3d_context(pctx); 146b8e80941Smrg 147b8e80941Smrg if (sample_count <= 1) { 148b8e80941Smrg xy[0] = 0.5; 149b8e80941Smrg xy[1] = 0.5; 150b8e80941Smrg } else { 151b8e80941Smrg static const int xoffsets_v33[] = { 1, -3, 3, -1 }; 152b8e80941Smrg static const int xoffsets_v42[] = { -1, 3, -3, 1 }; 153b8e80941Smrg const int *xoffsets = (v3d->screen->devinfo.ver >= 42 ? 154b8e80941Smrg xoffsets_v42 : xoffsets_v33); 155b8e80941Smrg 156b8e80941Smrg xy[0] = 0.5 + xoffsets[sample_index] * .125; 157b8e80941Smrg xy[1] = .125 + sample_index * .25; 158b8e80941Smrg } 159b8e80941Smrg} 160b8e80941Smrg 161b8e80941Smrgstruct pipe_context * 162b8e80941Smrgv3d_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) 163b8e80941Smrg{ 164b8e80941Smrg struct v3d_screen *screen = v3d_screen(pscreen); 165b8e80941Smrg struct v3d_context *v3d; 166b8e80941Smrg 167b8e80941Smrg /* Prevent dumping of the shaders built during context setup. */ 168b8e80941Smrg uint32_t saved_shaderdb_flag = V3D_DEBUG & V3D_DEBUG_SHADERDB; 169b8e80941Smrg V3D_DEBUG &= ~V3D_DEBUG_SHADERDB; 170b8e80941Smrg 171b8e80941Smrg v3d = rzalloc(NULL, struct v3d_context); 172b8e80941Smrg if (!v3d) 173b8e80941Smrg return NULL; 174b8e80941Smrg struct pipe_context *pctx = &v3d->base; 175b8e80941Smrg 176b8e80941Smrg v3d->screen = screen; 177b8e80941Smrg 178b8e80941Smrg int ret = drmSyncobjCreate(screen->fd, DRM_SYNCOBJ_CREATE_SIGNALED, 179b8e80941Smrg &v3d->out_sync); 180b8e80941Smrg if (ret) { 181b8e80941Smrg ralloc_free(v3d); 182b8e80941Smrg return NULL; 183b8e80941Smrg } 184b8e80941Smrg 185b8e80941Smrg pctx->screen = pscreen; 186b8e80941Smrg pctx->priv = priv; 187b8e80941Smrg pctx->destroy = v3d_context_destroy; 188b8e80941Smrg pctx->flush = v3d_pipe_flush; 189b8e80941Smrg pctx->memory_barrier = v3d_memory_barrier; 190b8e80941Smrg pctx->set_debug_callback = v3d_set_debug_callback; 191b8e80941Smrg pctx->invalidate_resource = v3d_invalidate_resource; 192b8e80941Smrg pctx->get_sample_position = v3d_get_sample_position; 193b8e80941Smrg 194b8e80941Smrg if (screen->devinfo.ver >= 41) { 195b8e80941Smrg v3d41_draw_init(pctx); 196b8e80941Smrg v3d41_state_init(pctx); 197b8e80941Smrg } else { 198b8e80941Smrg v3d33_draw_init(pctx); 199b8e80941Smrg v3d33_state_init(pctx); 200b8e80941Smrg } 201b8e80941Smrg v3d_program_init(pctx); 202b8e80941Smrg v3d_query_init(pctx); 203b8e80941Smrg v3d_resource_context_init(pctx); 204b8e80941Smrg 205b8e80941Smrg v3d_job_init(v3d); 206b8e80941Smrg 207b8e80941Smrg v3d->fd = screen->fd; 208b8e80941Smrg 209b8e80941Smrg slab_create_child(&v3d->transfer_pool, &screen->transfer_pool); 210b8e80941Smrg 211b8e80941Smrg v3d->uploader = u_upload_create_default(&v3d->base); 212b8e80941Smrg v3d->base.stream_uploader = v3d->uploader; 213b8e80941Smrg v3d->base.const_uploader = v3d->uploader; 214b8e80941Smrg v3d->state_uploader = u_upload_create(&v3d->base, 215b8e80941Smrg 4096, 216b8e80941Smrg PIPE_BIND_CONSTANT_BUFFER, 217b8e80941Smrg PIPE_USAGE_STREAM, 0); 218b8e80941Smrg 219b8e80941Smrg v3d->blitter = util_blitter_create(pctx); 220b8e80941Smrg if (!v3d->blitter) 221b8e80941Smrg goto fail; 222b8e80941Smrg v3d->blitter->use_index_buffer = true; 223b8e80941Smrg 224b8e80941Smrg v3d->primconvert = util_primconvert_create(pctx, 225b8e80941Smrg (1 << PIPE_PRIM_QUADS) - 1); 226b8e80941Smrg if (!v3d->primconvert) 227b8e80941Smrg goto fail; 228b8e80941Smrg 229b8e80941Smrg V3D_DEBUG |= saved_shaderdb_flag; 230b8e80941Smrg 231b8e80941Smrg v3d->sample_mask = (1 << V3D_MAX_SAMPLES) - 1; 232b8e80941Smrg v3d->active_queries = true; 233b8e80941Smrg 234b8e80941Smrg return &v3d->base; 235b8e80941Smrg 236b8e80941Smrgfail: 237b8e80941Smrg pctx->destroy(pctx); 238b8e80941Smrg return NULL; 239b8e80941Smrg} 240