1b8e80941Smrg/* 2b8e80941Smrg * Copyright 2014, 2015 Red Hat. 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 * on the rights to use, copy, modify, merge, publish, distribute, sub 8b8e80941Smrg * license, and/or sell copies of the Software, and to permit persons to whom 9b8e80941Smrg * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL 18b8e80941Smrg * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19b8e80941Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20b8e80941Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21b8e80941Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. 22b8e80941Smrg */ 23b8e80941Smrg 24b8e80941Smrg#include "util/u_inlines.h" 25b8e80941Smrg#include "util/u_memory.h" 26b8e80941Smrg#include "virgl_context.h" 27b8e80941Smrg#include "virgl_resource.h" 28b8e80941Smrg#include "virgl_screen.h" 29b8e80941Smrg 30b8e80941Smrgstatic void *virgl_buffer_transfer_map(struct pipe_context *ctx, 31b8e80941Smrg struct pipe_resource *resource, 32b8e80941Smrg unsigned level, 33b8e80941Smrg unsigned usage, 34b8e80941Smrg const struct pipe_box *box, 35b8e80941Smrg struct pipe_transfer **transfer) 36b8e80941Smrg{ 37b8e80941Smrg struct virgl_context *vctx = virgl_context(ctx); 38b8e80941Smrg struct virgl_screen *vs = virgl_screen(ctx->screen); 39b8e80941Smrg struct virgl_resource *vbuf = virgl_resource(resource); 40b8e80941Smrg struct virgl_transfer *trans; 41b8e80941Smrg bool readback; 42b8e80941Smrg bool flush = false; 43b8e80941Smrg 44b8e80941Smrg trans = virgl_resource_create_transfer(&vctx->transfer_pool, resource, 45b8e80941Smrg &vbuf->metadata, level, usage, box); 46b8e80941Smrg if (usage & PIPE_TRANSFER_READ) 47b8e80941Smrg flush = true; 48b8e80941Smrg else 49b8e80941Smrg flush = virgl_res_needs_flush(vctx, trans); 50b8e80941Smrg 51b8e80941Smrg if (flush) 52b8e80941Smrg ctx->flush(ctx, NULL, 0); 53b8e80941Smrg 54b8e80941Smrg readback = virgl_res_needs_readback(vctx, vbuf, usage, 0); 55b8e80941Smrg if (readback) 56b8e80941Smrg vs->vws->transfer_get(vs->vws, vbuf->hw_res, box, trans->base.stride, 57b8e80941Smrg trans->l_stride, trans->offset, level); 58b8e80941Smrg 59b8e80941Smrg if (readback || flush) 60b8e80941Smrg vs->vws->resource_wait(vs->vws, vbuf->hw_res); 61b8e80941Smrg 62b8e80941Smrg trans->hw_res_map = vs->vws->resource_map(vs->vws, vbuf->hw_res); 63b8e80941Smrg if (!trans->hw_res_map) { 64b8e80941Smrg virgl_resource_destroy_transfer(&vctx->transfer_pool, trans); 65b8e80941Smrg return NULL; 66b8e80941Smrg } 67b8e80941Smrg 68b8e80941Smrg *transfer = &trans->base; 69b8e80941Smrg return trans->hw_res_map + trans->offset; 70b8e80941Smrg} 71b8e80941Smrg 72b8e80941Smrgstatic void virgl_buffer_transfer_unmap(struct pipe_context *ctx, 73b8e80941Smrg struct pipe_transfer *transfer) 74b8e80941Smrg{ 75b8e80941Smrg struct virgl_context *vctx = virgl_context(ctx); 76b8e80941Smrg struct virgl_transfer *trans = virgl_transfer(transfer); 77b8e80941Smrg 78b8e80941Smrg if (trans->base.usage & PIPE_TRANSFER_WRITE) { 79b8e80941Smrg if (transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT) { 80b8e80941Smrg if (trans->range.end <= trans->range.start) { 81b8e80941Smrg virgl_resource_destroy_transfer(&vctx->transfer_pool, trans); 82b8e80941Smrg return; 83b8e80941Smrg } 84b8e80941Smrg 85b8e80941Smrg transfer->box.x += trans->range.start; 86b8e80941Smrg transfer->box.width = trans->range.end - trans->range.start; 87b8e80941Smrg trans->offset = transfer->box.x; 88b8e80941Smrg } 89b8e80941Smrg 90b8e80941Smrg virgl_transfer_queue_unmap(&vctx->queue, trans); 91b8e80941Smrg } else 92b8e80941Smrg virgl_resource_destroy_transfer(&vctx->transfer_pool, trans); 93b8e80941Smrg} 94b8e80941Smrg 95b8e80941Smrgstatic void virgl_buffer_transfer_flush_region(struct pipe_context *ctx, 96b8e80941Smrg struct pipe_transfer *transfer, 97b8e80941Smrg const struct pipe_box *box) 98b8e80941Smrg{ 99b8e80941Smrg struct virgl_transfer *trans = virgl_transfer(transfer); 100b8e80941Smrg 101b8e80941Smrg /* 102b8e80941Smrg * FIXME: This is not optimal. For example, 103b8e80941Smrg * 104b8e80941Smrg * glMapBufferRange(.., 0, 100, GL_MAP_FLUSH_EXPLICIT_BIT) 105b8e80941Smrg * glFlushMappedBufferRange(.., 25, 30) 106b8e80941Smrg * glFlushMappedBufferRange(.., 65, 70) 107b8e80941Smrg * 108b8e80941Smrg * We'll end up flushing 25 --> 70. 109b8e80941Smrg */ 110b8e80941Smrg util_range_add(&trans->range, box->x, box->x + box->width); 111b8e80941Smrg} 112b8e80941Smrg 113b8e80941Smrgstatic const struct u_resource_vtbl virgl_buffer_vtbl = 114b8e80941Smrg{ 115b8e80941Smrg u_default_resource_get_handle, /* get_handle */ 116b8e80941Smrg virgl_resource_destroy, /* resource_destroy */ 117b8e80941Smrg virgl_buffer_transfer_map, /* transfer_map */ 118b8e80941Smrg virgl_buffer_transfer_flush_region, /* transfer_flush_region */ 119b8e80941Smrg virgl_buffer_transfer_unmap, /* transfer_unmap */ 120b8e80941Smrg}; 121b8e80941Smrg 122b8e80941Smrgvoid virgl_buffer_init(struct virgl_resource *res) 123b8e80941Smrg{ 124b8e80941Smrg res->u.vtbl = &virgl_buffer_vtbl; 125b8e80941Smrg} 126