12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "util/u_inlines.h" 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "util/u_memory.h" 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "util/u_math.h" 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nouveau_screen.h" 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nouveau_context.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nouveau_winsys.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nouveau_fence.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nouveau_buffer.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "nouveau_mm.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct nouveau_transfer { 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct pipe_transfer base; 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static INLINE struct nouveau_transfer * 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_transfer(struct pipe_transfer *transfer) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return (struct nouveau_transfer *)transfer; 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static INLINE boolean 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_buffer_allocate(struct nouveau_screen *screen, 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nv04_resource *buf, unsigned domain) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t size = buf->base.width0; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (buf->base.bind & PIPE_BIND_CONSTANT_BUFFER) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size = align(size, 0x100); 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (domain == NOUVEAU_BO_VRAM) { 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buf->mm = nouveau_mm_allocate(screen->mm_VRAM, size, 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &buf->bo, &buf->offset); 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!buf->bo) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return nouveau_buffer_allocate(screen, buf, NOUVEAU_BO_GART); 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (domain == NOUVEAU_BO_GART) { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buf->mm = nouveau_mm_allocate(screen->mm_GART, size, 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &buf->bo, &buf->offset); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!buf->bo) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (domain != NOUVEAU_BO_GART) { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!buf->data) { 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buf->data = MALLOC(buf->base.width0); 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!buf->data) 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buf->domain = domain; 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (buf->bo) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buf->address = buf->bo->offset + buf->offset; 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return TRUE; 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static INLINE void 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)release_allocation(struct nouveau_mm_allocation **mm, 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nouveau_fence *fence) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_fence_work(fence, nouveau_mm_free_work, *mm); 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (*mm) = NULL; 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)INLINE void 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_buffer_release_gpu_storage(struct nv04_resource *buf) 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_bo_ref(NULL, &buf->bo); 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (buf->mm) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) release_allocation(&buf->mm, buf->fence); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buf->domain = 0; 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static INLINE boolean 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_buffer_reallocate(struct nouveau_screen *screen, 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nv04_resource *buf, unsigned domain) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_buffer_release_gpu_storage(buf); 82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return nouveau_buffer_allocate(screen, buf, domain); 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_buffer_destroy(struct pipe_screen *pscreen, 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct pipe_resource *presource) 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nv04_resource *res = nv04_resource(presource); 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_buffer_release_gpu_storage(res); 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (res->data && !(res->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY)) 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FREE(res->data); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_fence_ref(NULL, &res->fence); 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_fence_ref(NULL, &res->fence_wr); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FREE(res); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* Maybe just migrate to GART right away if we actually need to do this. */ 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)boolean 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_buffer_download(struct nouveau_context *nv, struct nv04_resource *buf, 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned start, unsigned size) 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nouveau_mm_allocation *mm; 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nouveau_bo *bounce = NULL; 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t offset; 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert(buf->domain == NOUVEAU_BO_VRAM); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mm = nouveau_mm_allocate(nv->screen->mm_GART, size, &bounce, &offset); 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!bounce) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nv->copy_data(nv, bounce, offset, NOUVEAU_BO_GART, 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buf->bo, buf->offset + start, NOUVEAU_BO_VRAM, size); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (nouveau_bo_map(bounce, NOUVEAU_BO_RD, nv->screen->client)) 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(buf->data + start, (uint8_t *)bounce->map + offset, size); 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buf->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING; 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_bo_ref(NULL, &bounce); 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mm) 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_mm_free(mm); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return TRUE; 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static boolean 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_buffer_upload(struct nouveau_context *nv, struct nv04_resource *buf, 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned start, unsigned size) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nouveau_mm_allocation *mm; 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nouveau_bo *bounce = NULL; 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t offset; 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (size <= 192 && (nv->push_data || nv->push_cb)) { 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (buf->base.bind & PIPE_BIND_CONSTANT_BUFFER) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nv->push_cb(nv, buf->bo, buf->domain, buf->offset, buf->base.width0, 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) start, size / 4, (const uint32_t *)(buf->data + start)); 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nv->push_data(nv, buf->bo, buf->offset + start, buf->domain, 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size, buf->data + start); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return TRUE; 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mm = nouveau_mm_allocate(nv->screen->mm_GART, size, &bounce, &offset); 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!bounce) 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_bo_map(bounce, 0, nv->screen->client); 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy((uint8_t *)bounce->map + offset, buf->data + start, size); 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nv->copy_data(nv, buf->bo, buf->offset + start, NOUVEAU_BO_VRAM, 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bounce, offset, NOUVEAU_BO_GART, size); 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_bo_ref(NULL, &bounce); 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mm) 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) release_allocation(&mm, nv->screen->fence.current); 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (start == 0 && size == buf->base.width0) 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buf->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING; 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return TRUE; 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static struct pipe_transfer * 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_buffer_transfer_get(struct pipe_context *pipe, 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct pipe_resource *resource, 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned level, unsigned usage, 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const struct pipe_box *box) 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nv04_resource *buf = nv04_resource(resource); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nouveau_context *nv = nouveau_context(pipe); 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nouveau_transfer *xfr = CALLOC_STRUCT(nouveau_transfer); 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!xfr) 1807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return NULL; 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) xfr->base.resource = resource; 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) xfr->base.box.x = box->x; 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) xfr->base.box.width = box->width; 1857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) xfr->base.usage = usage; 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (buf->domain == NOUVEAU_BO_VRAM) { 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (usage & PIPE_TRANSFER_READ) { 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (buf->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_buffer_download(nv, buf, 0, buf->base.width0); 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return &xfr->base; 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_buffer_transfer_destroy(struct pipe_context *pipe, 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct pipe_transfer *transfer) 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nv04_resource *buf = nv04_resource(transfer->resource); 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nouveau_transfer *xfr = nouveau_transfer(transfer); 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nouveau_context *nv = nouveau_context(pipe); 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (xfr->base.usage & PIPE_TRANSFER_WRITE) { 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (buf->domain == NOUVEAU_BO_VRAM) { 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_buffer_upload(nv, buf, transfer->box.x, transfer->box.width); 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (buf->domain != 0 && (buf->base.bind & (PIPE_BIND_VERTEX_BUFFER | 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PIPE_BIND_INDEX_BUFFER))) 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_context(pipe)->vbo_dirty = TRUE; 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FREE(xfr); 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static INLINE boolean 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_buffer_sync(struct nv04_resource *buf, unsigned rw) 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){ 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rw == PIPE_TRANSFER_READ) { 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!buf->fence_wr) 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return TRUE; 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!nouveau_fence_wait(buf->fence_wr)) 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!buf->fence) 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return TRUE; 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!nouveau_fence_wait(buf->fence)) 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_fence_ref(NULL, &buf->fence); 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_fence_ref(NULL, &buf->fence_wr); 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return TRUE; 2377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static INLINE boolean 2407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)nouveau_buffer_busy(struct nv04_resource *buf, unsigned rw) 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rw == PIPE_TRANSFER_READ) 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (buf->fence_wr && !nouveau_fence_signalled(buf->fence_wr)); 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return (buf->fence && !nouveau_fence_signalled(buf->fence)); 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void * 2497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)nouveau_buffer_transfer_map(struct pipe_context *pipe, 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct pipe_transfer *transfer) 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nouveau_context *nv = nouveau_context(pipe); 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nouveau_transfer *xfr = nouveau_transfer(transfer); 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nv04_resource *buf = nv04_resource(transfer->resource); 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nouveau_bo *bo = buf->bo; 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8_t *map; 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int ret; 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t offset = xfr->base.box.x; 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t flags = 0; 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (buf->domain != NOUVEAU_BO_GART) 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return buf->data + offset; 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!buf->mm) 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) flags = nouveau_screen_transfer_flags(xfr->base.usage); 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) offset += buf->offset; 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret = nouveau_bo_map(buf->bo, flags, nv->screen->client); 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (ret) 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) map = (uint8_t *)bo->map + offset; 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (buf->mm) { 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (xfr->base.usage & PIPE_TRANSFER_DONTBLOCK) { 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (nouveau_buffer_busy(buf, xfr->base.usage & PIPE_TRANSFER_READ_WRITE)) 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!(xfr->base.usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_buffer_sync(buf, xfr->base.usage & PIPE_TRANSFER_READ_WRITE); 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return map; 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_buffer_transfer_flush_region(struct pipe_context *pipe, 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct pipe_transfer *transfer, 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const struct pipe_box *box) 2927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles){ 2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if 0 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nv04_resource *res = nv04_resource(transfer->resource); 2957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) struct nouveau_bo *bo = res->bo; 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned offset = res->offset + transfer->box.x + box->x; 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* not using non-snoop system memory yet, no need for cflush */ 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (1) 3007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* XXX: maybe need to upload for VRAM buffers here */ 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 3047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_buffer_transfer_unmap(struct pipe_context *pipe, 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct pipe_transfer *transfer) 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void * 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_resource_map_offset(struct nouveau_context *nv, 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nv04_resource *res, uint32_t offset, 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32_t flags) 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((res->domain == NOUVEAU_BO_VRAM) && 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING)) 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_buffer_download(nv, res, 0, res->base.width0); 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ((res->domain != NOUVEAU_BO_GART) || 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (res->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY)) 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return res->data + offset; 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (res->mm) { 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned rw; 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rw = (flags & NOUVEAU_BO_WR) ? PIPE_TRANSFER_WRITE : PIPE_TRANSFER_READ; 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_buffer_sync(res, rw); 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (nouveau_bo_map(res->bo, 0, NULL)) 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (nouveau_bo_map(res->bo, flags, nv->screen->client)) 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (uint8_t *)res->bo->map + res->offset + offset; 3377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const struct u_resource_vtbl nouveau_buffer_vtbl = 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) u_default_resource_get_handle, /* get_handle */ 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_buffer_destroy, /* resource_destroy */ 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_buffer_transfer_get, /* get_transfer */ 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_buffer_transfer_destroy, /* transfer_destroy */ 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_buffer_transfer_map, /* transfer_map */ 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_buffer_transfer_flush_region, /* transfer_flush_region */ 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_buffer_transfer_unmap, /* transfer_unmap */ 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) u_default_transfer_inline_write /* transfer_inline_write */ 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct pipe_resource * 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_buffer_create(struct pipe_screen *pscreen, 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const struct pipe_resource *templ) 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nouveau_screen *screen = nouveau_screen(pscreen); 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nv04_resource *buffer; 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) boolean ret; 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer = CALLOC_STRUCT(nv04_resource); 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!buffer) 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->base = *templ; 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->vtbl = &nouveau_buffer_vtbl; 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pipe_reference_init(&buffer->base.reference, 1); 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->base.screen = pscreen; 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (buffer->base.bind & 3707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) (screen->vidmem_bindings & screen->sysmem_bindings)) { 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (buffer->base.usage) { 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case PIPE_USAGE_DEFAULT: 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case PIPE_USAGE_IMMUTABLE: 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case PIPE_USAGE_STATIC: 3757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) buffer->domain = NOUVEAU_BO_VRAM; 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case PIPE_USAGE_DYNAMIC: 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case PIPE_USAGE_STAGING: 3797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case PIPE_USAGE_STREAM: 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->domain = NOUVEAU_BO_GART; 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 3837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) assert(0); 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (buffer->base.bind & screen->vidmem_bindings) 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->domain = NOUVEAU_BO_VRAM; 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (buffer->base.bind & screen->sysmem_bindings) 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->domain = NOUVEAU_BO_GART; 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret = nouveau_buffer_allocate(screen, buffer, buffer->domain); 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (ret == FALSE) 3967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) goto fail; 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return &buffer->base; 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)fail: 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FREE(buffer); 4027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return NULL; 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct pipe_resource * 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_user_buffer_create(struct pipe_screen *pscreen, void *ptr, 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned bytes, unsigned bind) 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nv04_resource *buffer; 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer = CALLOC_STRUCT(nv04_resource); 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!buffer) 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pipe_reference_init(&buffer->base.reference, 1); 4177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) buffer->vtbl = &nouveau_buffer_vtbl; 4187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) buffer->base.screen = pscreen; 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->base.format = PIPE_FORMAT_R8_UNORM; 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->base.usage = PIPE_USAGE_IMMUTABLE; 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->base.bind = bind; 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->base.width0 = bytes; 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->base.height0 = 1; 4247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) buffer->base.depth0 = 1; 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->data = ptr; 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buffer->status = NOUVEAU_BUFFER_STATUS_USER_MEMORY; 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return &buffer->base; 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* Like download, but for GART buffers. Merge ? */ 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static INLINE boolean 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_buffer_data_fetch(struct nouveau_context *nv, struct nv04_resource *buf, 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nouveau_bo *bo, unsigned offset, unsigned size) 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!buf->data) { 4387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) buf->data = MALLOC(size); 4397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!buf->data) 4407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return FALSE; 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (nouveau_bo_map(bo, NOUVEAU_BO_RD, nv->screen->client)) 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(buf->data, (uint8_t *)bo->map + offset, size); 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return TRUE; 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* Migrate a linear buffer (vertex, index, constants) USER -> GART -> VRAM. */ 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)boolean 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_buffer_migrate(struct nouveau_context *nv, 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nv04_resource *buf, const unsigned new_domain) 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nouveau_screen *screen = nv->screen; 4557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) struct nouveau_bo *bo; 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned old_domain = buf->domain; 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned size = buf->base.width0; 4587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) unsigned offset; 4597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) int ret; 4607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 4617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) assert(new_domain != old_domain); 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_domain == NOUVEAU_BO_GART && old_domain == 0) { 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!nouveau_buffer_allocate(screen, buf, new_domain)) 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret = nouveau_bo_map(buf->bo, 0, nv->screen->client); 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (ret) 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ret; 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy((uint8_t *)buf->bo->map + buf->offset, buf->data, size); 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FREE(buf->data); 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (old_domain != 0 && new_domain != 0) { 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nouveau_mm_allocation *mm = buf->mm; 4747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 4757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (new_domain == NOUVEAU_BO_VRAM) { 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* keep a system memory copy of our data in case we hit a fallback */ 4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!nouveau_buffer_data_fetch(nv, buf, buf->bo, buf->offset, size)) 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (nouveau_mesa_debug) 4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) debug_printf("migrating %u KiB to VRAM\n", size / 1024); 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) offset = buf->offset; 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bo = buf->bo; 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buf->bo = NULL; 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buf->mm = NULL; 4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_buffer_allocate(screen, buf, new_domain); 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nv->copy_data(nv, buf->bo, buf->offset, new_domain, 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bo, offset, old_domain, buf->base.width0); 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_bo_ref(NULL, &bo); 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (mm) 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) release_allocation(&mm, screen->fence.current); 4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else 4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_domain == NOUVEAU_BO_VRAM && old_domain == 0) { 4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!nouveau_buffer_allocate(screen, buf, NOUVEAU_BO_VRAM)) 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!nouveau_buffer_upload(nv, buf, 0, buf->base.width0)) 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return FALSE; 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert(buf->domain == new_domain); 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return TRUE; 5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* Migrate data from glVertexAttribPointer(non-VBO) user buffers to GART. 5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * We'd like to only allocate @size bytes here, but then we'd have to rebase 5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * the vertex indices ... 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)boolean 5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_user_buffer_upload(struct nouveau_context *nv, 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nv04_resource *buf, 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned base, unsigned size) 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct nouveau_screen *screen = nouveau_screen(buf->base.screen); 5187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) int ret; 5197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert(buf->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY); 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buf->base.width0 = base + size; 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!nouveau_buffer_reallocate(screen, buf, NOUVEAU_BO_GART)) 5247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return FALSE; 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret = nouveau_bo_map(buf->bo, 0, nv->screen->client); 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (ret) 5287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return FALSE; 5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy((uint8_t *)buf->bo->map + buf->offset + base, buf->data + base, size); 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return TRUE; 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* Scratch data allocation. */ 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static INLINE int 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_scratch_bo_alloc(struct nouveau_context *nv, struct nouveau_bo **pbo, 5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned size) 5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return nouveau_bo_new(nv->screen->device, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4096, size, NULL, pbo); 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void 5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_scratch_runout_release(struct nouveau_context *nv) 5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!nv->scratch.nr_runout) 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) do { 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) --nv->scratch.nr_runout; 5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_bo_ref(NULL, &nv->scratch.runout[nv->scratch.nr_runout]); 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } while (nv->scratch.nr_runout); 5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FREE(nv->scratch.runout); 5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nv->scratch.end = 0; 5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nv->scratch.runout = NULL; 5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* Allocate an extra bo if we can't fit everything we need simultaneously. 5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * (Could happen for very large user arrays.) 5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static INLINE boolean 5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)nouveau_scratch_runout(struct nouveau_context *nv, unsigned size) 5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){ 5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int ret; 5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const unsigned n = nv->scratch.nr_runout++; 5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nv->scratch.runout = REALLOC(nv->scratch.runout, 5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (n + 0) * sizeof(*nv->scratch.runout), 5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (n + 1) * sizeof(*nv->scratch.runout)); 5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nv->scratch.runout[n] = NULL; 5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret = nouveau_scratch_bo_alloc(nv, &nv->scratch.runout[n], size); 5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!ret) { 5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret = nouveau_bo_map(nv->scratch.runout[n], 0, NULL); 5777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (ret) 5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nouveau_bo_ref(NULL, &nv->scratch.runout[--nv->scratch.nr_runout]); 5797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!ret) { 5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nv->scratch.current = nv->scratch.runout[n]; 5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nv->scratch.offset = 0; 5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nv->scratch.end = size; 5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) nv->scratch.map = nv->scratch.current->map; 5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return !ret; 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* Continue to next scratch buffer, if available (no wrapping, large enough). 5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Allocate it if it has not yet been created. 5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 592static INLINE boolean 593nouveau_scratch_next(struct nouveau_context *nv, unsigned size) 594{ 595 struct nouveau_bo *bo; 596 int ret; 597 const unsigned i = (nv->scratch.id + 1) % NOUVEAU_MAX_SCRATCH_BUFS; 598 599 if ((size > nv->scratch.bo_size) || (i == nv->scratch.wrap)) 600 return FALSE; 601 nv->scratch.id = i; 602 603 bo = nv->scratch.bo[i]; 604 if (!bo) { 605 ret = nouveau_scratch_bo_alloc(nv, &bo, nv->scratch.bo_size); 606 if (ret) 607 return FALSE; 608 nv->scratch.bo[i] = bo; 609 } 610 nv->scratch.current = bo; 611 nv->scratch.offset = 0; 612 nv->scratch.end = nv->scratch.bo_size; 613 614 ret = nouveau_bo_map(bo, NOUVEAU_BO_WR, nv->screen->client); 615 if (!ret) 616 nv->scratch.map = bo->map; 617 return !ret; 618} 619 620static boolean 621nouveau_scratch_more(struct nouveau_context *nv, unsigned min_size) 622{ 623 boolean ret; 624 625 ret = nouveau_scratch_next(nv, min_size); 626 if (!ret) 627 ret = nouveau_scratch_runout(nv, min_size); 628 return ret; 629} 630 631 632/* Copy data to a scratch buffer and return address & bo the data resides in. */ 633uint64_t 634nouveau_scratch_data(struct nouveau_context *nv, 635 const void *data, unsigned base, unsigned size, 636 struct nouveau_bo **bo) 637{ 638 unsigned bgn = MAX2(base, nv->scratch.offset); 639 unsigned end = bgn + size; 640 641 if (end >= nv->scratch.end) { 642 end = base + size; 643 if (!nouveau_scratch_more(nv, end)) 644 return 0; 645 bgn = base; 646 } 647 nv->scratch.offset = align(end, 4); 648 649 memcpy(nv->scratch.map + bgn, (const uint8_t *)data + base, size); 650 651 *bo = nv->scratch.current; 652 return (*bo)->offset + (bgn - base); 653} 654 655void * 656nouveau_scratch_get(struct nouveau_context *nv, 657 unsigned size, uint64_t *gpu_addr, struct nouveau_bo **pbo) 658{ 659 unsigned bgn = nv->scratch.offset; 660 unsigned end = nv->scratch.offset + size; 661 662 if (end >= nv->scratch.end) { 663 end = size; 664 if (!nouveau_scratch_more(nv, end)) 665 return NULL; 666 bgn = 0; 667 } 668 nv->scratch.offset = align(end, 4); 669 670 *pbo = nv->scratch.current; 671 *gpu_addr = nv->scratch.current->offset + bgn; 672 return nv->scratch.map + bgn; 673} 674