1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2010 Red Hat Inc. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: Dave Airlie 24bf215546Sopenharmony_ci */ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include <stdio.h> 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "util/u_inlines.h" 29bf215546Sopenharmony_ci#include "util/u_memory.h" 30bf215546Sopenharmony_ci#include "util/u_upload_mgr.h" 31bf215546Sopenharmony_ci#include "util/u_math.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#include "r300_screen_buffer.h" 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_civoid r300_upload_index_buffer(struct r300_context *r300, 36bf215546Sopenharmony_ci struct pipe_resource **index_buffer, 37bf215546Sopenharmony_ci unsigned index_size, unsigned *start, 38bf215546Sopenharmony_ci unsigned count, const uint8_t *ptr) 39bf215546Sopenharmony_ci{ 40bf215546Sopenharmony_ci unsigned index_offset; 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci *index_buffer = NULL; 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci u_upload_data(r300->uploader, 45bf215546Sopenharmony_ci 0, count * index_size, 4, 46bf215546Sopenharmony_ci ptr + (*start * index_size), 47bf215546Sopenharmony_ci &index_offset, 48bf215546Sopenharmony_ci index_buffer); 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci *start = index_offset / index_size; 51bf215546Sopenharmony_ci} 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_civoid r300_resource_destroy(struct pipe_screen *screen, 54bf215546Sopenharmony_ci struct pipe_resource *buf) 55bf215546Sopenharmony_ci{ 56bf215546Sopenharmony_ci if (buf->target == PIPE_BUFFER) { 57bf215546Sopenharmony_ci struct r300_resource *rbuf = r300_resource(buf); 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci align_free(rbuf->malloced_buffer); 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci if (rbuf->buf) 62bf215546Sopenharmony_ci pb_reference(&rbuf->buf, NULL); 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci FREE(rbuf); 65bf215546Sopenharmony_ci } else { 66bf215546Sopenharmony_ci struct r300_screen *rscreen = r300_screen(screen); 67bf215546Sopenharmony_ci struct r300_resource* tex = (struct r300_resource*)buf; 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci if (tex->tex.cmask_dwords) { 70bf215546Sopenharmony_ci mtx_lock(&rscreen->cmask_mutex); 71bf215546Sopenharmony_ci if (buf == rscreen->cmask_resource) { 72bf215546Sopenharmony_ci rscreen->cmask_resource = NULL; 73bf215546Sopenharmony_ci } 74bf215546Sopenharmony_ci mtx_unlock(&rscreen->cmask_mutex); 75bf215546Sopenharmony_ci } 76bf215546Sopenharmony_ci pb_reference(&tex->buf, NULL); 77bf215546Sopenharmony_ci FREE(tex); 78bf215546Sopenharmony_ci } 79bf215546Sopenharmony_ci} 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_civoid * 82bf215546Sopenharmony_cir300_buffer_transfer_map( struct pipe_context *context, 83bf215546Sopenharmony_ci struct pipe_resource *resource, 84bf215546Sopenharmony_ci unsigned level, 85bf215546Sopenharmony_ci unsigned usage, 86bf215546Sopenharmony_ci const struct pipe_box *box, 87bf215546Sopenharmony_ci struct pipe_transfer **ptransfer ) 88bf215546Sopenharmony_ci{ 89bf215546Sopenharmony_ci struct r300_context *r300 = r300_context(context); 90bf215546Sopenharmony_ci struct radeon_winsys *rws = r300->screen->rws; 91bf215546Sopenharmony_ci struct r300_resource *rbuf = r300_resource(resource); 92bf215546Sopenharmony_ci struct pipe_transfer *transfer; 93bf215546Sopenharmony_ci uint8_t *map; 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci transfer = slab_alloc(&r300->pool_transfers); 96bf215546Sopenharmony_ci transfer->resource = resource; 97bf215546Sopenharmony_ci transfer->level = level; 98bf215546Sopenharmony_ci transfer->usage = usage; 99bf215546Sopenharmony_ci transfer->box = *box; 100bf215546Sopenharmony_ci transfer->stride = 0; 101bf215546Sopenharmony_ci transfer->layer_stride = 0; 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci if (rbuf->malloced_buffer) { 104bf215546Sopenharmony_ci *ptransfer = transfer; 105bf215546Sopenharmony_ci return rbuf->malloced_buffer + box->x; 106bf215546Sopenharmony_ci } 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci if (usage & PIPE_MAP_DISCARD_WHOLE_RESOURCE && 109bf215546Sopenharmony_ci !(usage & PIPE_MAP_UNSYNCHRONIZED)) { 110bf215546Sopenharmony_ci assert(usage & PIPE_MAP_WRITE); 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci /* Check if mapping this buffer would cause waiting for the GPU. */ 113bf215546Sopenharmony_ci if (r300->rws->cs_is_buffer_referenced(&r300->cs, rbuf->buf, RADEON_USAGE_READWRITE) || 114bf215546Sopenharmony_ci !r300->rws->buffer_wait(r300->rws, rbuf->buf, 0, RADEON_USAGE_READWRITE)) { 115bf215546Sopenharmony_ci unsigned i; 116bf215546Sopenharmony_ci struct pb_buffer *new_buf; 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci /* Create a new one in the same pipe_resource. */ 119bf215546Sopenharmony_ci new_buf = r300->rws->buffer_create(r300->rws, rbuf->b.width0, 120bf215546Sopenharmony_ci R300_BUFFER_ALIGNMENT, 121bf215546Sopenharmony_ci rbuf->domain, 122bf215546Sopenharmony_ci RADEON_FLAG_NO_INTERPROCESS_SHARING); 123bf215546Sopenharmony_ci if (new_buf) { 124bf215546Sopenharmony_ci /* Discard the old buffer. */ 125bf215546Sopenharmony_ci pb_reference(&rbuf->buf, NULL); 126bf215546Sopenharmony_ci rbuf->buf = new_buf; 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci /* We changed the buffer, now we need to bind it where the old one was bound. */ 129bf215546Sopenharmony_ci for (i = 0; i < r300->nr_vertex_buffers; i++) { 130bf215546Sopenharmony_ci if (r300->vertex_buffer[i].buffer.resource == &rbuf->b) { 131bf215546Sopenharmony_ci r300->vertex_arrays_dirty = TRUE; 132bf215546Sopenharmony_ci break; 133bf215546Sopenharmony_ci } 134bf215546Sopenharmony_ci } 135bf215546Sopenharmony_ci } 136bf215546Sopenharmony_ci } 137bf215546Sopenharmony_ci } 138bf215546Sopenharmony_ci 139bf215546Sopenharmony_ci /* Buffers are never used for write, therefore mapping for read can be 140bf215546Sopenharmony_ci * unsynchronized. */ 141bf215546Sopenharmony_ci if (!(usage & PIPE_MAP_WRITE)) { 142bf215546Sopenharmony_ci usage |= PIPE_MAP_UNSYNCHRONIZED; 143bf215546Sopenharmony_ci } 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci map = rws->buffer_map(rws, rbuf->buf, &r300->cs, usage); 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci if (!map) { 148bf215546Sopenharmony_ci slab_free(&r300->pool_transfers, transfer); 149bf215546Sopenharmony_ci return NULL; 150bf215546Sopenharmony_ci } 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci *ptransfer = transfer; 153bf215546Sopenharmony_ci return map + box->x; 154bf215546Sopenharmony_ci} 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_civoid r300_buffer_transfer_unmap( struct pipe_context *pipe, 157bf215546Sopenharmony_ci struct pipe_transfer *transfer ) 158bf215546Sopenharmony_ci{ 159bf215546Sopenharmony_ci struct r300_context *r300 = r300_context(pipe); 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci slab_free(&r300->pool_transfers, transfer); 162bf215546Sopenharmony_ci} 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_cistruct pipe_resource *r300_buffer_create(struct pipe_screen *screen, 165bf215546Sopenharmony_ci const struct pipe_resource *templ) 166bf215546Sopenharmony_ci{ 167bf215546Sopenharmony_ci struct r300_screen *r300screen = r300_screen(screen); 168bf215546Sopenharmony_ci struct r300_resource *rbuf; 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci rbuf = MALLOC_STRUCT(r300_resource); 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci rbuf->b = *templ; 173bf215546Sopenharmony_ci pipe_reference_init(&rbuf->b.reference, 1); 174bf215546Sopenharmony_ci rbuf->b.screen = screen; 175bf215546Sopenharmony_ci rbuf->domain = RADEON_DOMAIN_GTT; 176bf215546Sopenharmony_ci rbuf->buf = NULL; 177bf215546Sopenharmony_ci rbuf->malloced_buffer = NULL; 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci /* Allocate constant buffers and SWTCL vertex and index buffers in RAM. 180bf215546Sopenharmony_ci * Note that uploaded index buffers use the flag PIPE_BIND_CUSTOM, so that 181bf215546Sopenharmony_ci * we can distinguish them from user-created buffers. 182bf215546Sopenharmony_ci */ 183bf215546Sopenharmony_ci if (templ->bind & PIPE_BIND_CONSTANT_BUFFER || 184bf215546Sopenharmony_ci (!r300screen->caps.has_tcl && !(templ->bind & PIPE_BIND_CUSTOM))) { 185bf215546Sopenharmony_ci rbuf->malloced_buffer = align_malloc(templ->width0, 64); 186bf215546Sopenharmony_ci return &rbuf->b; 187bf215546Sopenharmony_ci } 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci rbuf->buf = 190bf215546Sopenharmony_ci r300screen->rws->buffer_create(r300screen->rws, rbuf->b.width0, 191bf215546Sopenharmony_ci R300_BUFFER_ALIGNMENT, 192bf215546Sopenharmony_ci rbuf->domain, 193bf215546Sopenharmony_ci RADEON_FLAG_NO_INTERPROCESS_SHARING); 194bf215546Sopenharmony_ci if (!rbuf->buf) { 195bf215546Sopenharmony_ci FREE(rbuf); 196bf215546Sopenharmony_ci return NULL; 197bf215546Sopenharmony_ci } 198bf215546Sopenharmony_ci return &rbuf->b; 199bf215546Sopenharmony_ci} 200