Path: blob/21.2-virgl/src/gallium/drivers/r300/r300_screen_buffer.c
4570 views
/*1* Copyright 2010 Red Hat Inc.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* on the rights to use, copy, modify, merge, publish, distribute, sub7* license, and/or sell copies of the Software, and to permit persons to whom8* the Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,18* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR19* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE20* USE OR OTHER DEALINGS IN THE SOFTWARE.21*22* Authors: Dave Airlie23*/2425#include <stdio.h>2627#include "util/u_inlines.h"28#include "util/u_memory.h"29#include "util/u_upload_mgr.h"30#include "util/u_math.h"3132#include "r300_screen_buffer.h"3334void r300_upload_index_buffer(struct r300_context *r300,35struct pipe_resource **index_buffer,36unsigned index_size, unsigned *start,37unsigned count, const uint8_t *ptr)38{39unsigned index_offset;4041*index_buffer = NULL;4243u_upload_data(r300->uploader,440, count * index_size, 4,45ptr + (*start * index_size),46&index_offset,47index_buffer);4849*start = index_offset / index_size;50}5152void r300_resource_destroy(struct pipe_screen *screen,53struct pipe_resource *buf)54{55if (buf->target == PIPE_BUFFER) {56struct r300_resource *rbuf = r300_resource(buf);5758align_free(rbuf->malloced_buffer);5960if (rbuf->buf)61pb_reference(&rbuf->buf, NULL);6263FREE(rbuf);64} else {65struct r300_screen *rscreen = r300_screen(screen);66struct r300_resource* tex = (struct r300_resource*)buf;6768if (tex->tex.cmask_dwords) {69mtx_lock(&rscreen->cmask_mutex);70if (buf == rscreen->cmask_resource) {71rscreen->cmask_resource = NULL;72}73mtx_unlock(&rscreen->cmask_mutex);74}75pb_reference(&tex->buf, NULL);76FREE(tex);77}78}7980void *81r300_buffer_transfer_map( struct pipe_context *context,82struct pipe_resource *resource,83unsigned level,84unsigned usage,85const struct pipe_box *box,86struct pipe_transfer **ptransfer )87{88struct r300_context *r300 = r300_context(context);89struct radeon_winsys *rws = r300->screen->rws;90struct r300_resource *rbuf = r300_resource(resource);91struct pipe_transfer *transfer;92uint8_t *map;9394transfer = slab_alloc(&r300->pool_transfers);95transfer->resource = resource;96transfer->level = level;97transfer->usage = usage;98transfer->box = *box;99transfer->stride = 0;100transfer->layer_stride = 0;101102if (rbuf->malloced_buffer) {103*ptransfer = transfer;104return rbuf->malloced_buffer + box->x;105}106107if (usage & PIPE_MAP_DISCARD_WHOLE_RESOURCE &&108!(usage & PIPE_MAP_UNSYNCHRONIZED)) {109assert(usage & PIPE_MAP_WRITE);110111/* Check if mapping this buffer would cause waiting for the GPU. */112if (r300->rws->cs_is_buffer_referenced(&r300->cs, rbuf->buf, RADEON_USAGE_READWRITE) ||113!r300->rws->buffer_wait(r300->rws, rbuf->buf, 0, RADEON_USAGE_READWRITE)) {114unsigned i;115struct pb_buffer *new_buf;116117/* Create a new one in the same pipe_resource. */118new_buf = r300->rws->buffer_create(r300->rws, rbuf->b.width0,119R300_BUFFER_ALIGNMENT,120rbuf->domain,121RADEON_FLAG_NO_INTERPROCESS_SHARING);122if (new_buf) {123/* Discard the old buffer. */124pb_reference(&rbuf->buf, NULL);125rbuf->buf = new_buf;126127/* We changed the buffer, now we need to bind it where the old one was bound. */128for (i = 0; i < r300->nr_vertex_buffers; i++) {129if (r300->vertex_buffer[i].buffer.resource == &rbuf->b) {130r300->vertex_arrays_dirty = TRUE;131break;132}133}134}135}136}137138/* Buffers are never used for write, therefore mapping for read can be139* unsynchronized. */140if (!(usage & PIPE_MAP_WRITE)) {141usage |= PIPE_MAP_UNSYNCHRONIZED;142}143144map = rws->buffer_map(rws, rbuf->buf, &r300->cs, usage);145146if (!map) {147slab_free(&r300->pool_transfers, transfer);148return NULL;149}150151*ptransfer = transfer;152return map + box->x;153}154155void r300_buffer_transfer_unmap( struct pipe_context *pipe,156struct pipe_transfer *transfer )157{158struct r300_context *r300 = r300_context(pipe);159160slab_free(&r300->pool_transfers, transfer);161}162163struct pipe_resource *r300_buffer_create(struct pipe_screen *screen,164const struct pipe_resource *templ)165{166struct r300_screen *r300screen = r300_screen(screen);167struct r300_resource *rbuf;168169rbuf = MALLOC_STRUCT(r300_resource);170171rbuf->b = *templ;172pipe_reference_init(&rbuf->b.reference, 1);173rbuf->b.screen = screen;174rbuf->domain = RADEON_DOMAIN_GTT;175rbuf->buf = NULL;176rbuf->malloced_buffer = NULL;177178/* Allocate constant buffers and SWTCL vertex and index buffers in RAM.179* Note that uploaded index buffers use the flag PIPE_BIND_CUSTOM, so that180* we can distinguish them from user-created buffers.181*/182if (templ->bind & PIPE_BIND_CONSTANT_BUFFER ||183(!r300screen->caps.has_tcl && !(templ->bind & PIPE_BIND_CUSTOM))) {184rbuf->malloced_buffer = align_malloc(templ->width0, 64);185return &rbuf->b;186}187188rbuf->buf =189r300screen->rws->buffer_create(r300screen->rws, rbuf->b.width0,190R300_BUFFER_ALIGNMENT,191rbuf->domain,192RADEON_FLAG_NO_INTERPROCESS_SHARING);193if (!rbuf->buf) {194FREE(rbuf);195return NULL;196}197return &rbuf->b;198}199200201