168e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie/*
268e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * Copyright 2010 Red Hat Inc.
368e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie *
468e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * Permission is hereby granted, free of charge, to any person obtaining a
568e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * copy of this software and associated documentation files (the "Software"),
668e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * to deal in the Software without restriction, including without limitation
768e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * on the rights to use, copy, modify, merge, publish, distribute, sub
868e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * license, and/or sell copies of the Software, and to permit persons to whom
968e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * the Software is furnished to do so, subject to the following conditions:
1068e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie *
1168e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * The above copyright notice and this permission notice (including the next
1268e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * paragraph) shall be included in all copies or substantial portions of the
1368e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * Software.
1468e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie *
1568e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1668e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1768e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
1868e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
1968e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
2068e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
2168e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * USE OR OTHER DEALINGS IN THE SOFTWARE.
2268e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie *
2368e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie * Authors: Dave Airlie
2468e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie */
250b4df63609e9fb25319debd56142a90b11d75671Marek Olšák
2668e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie#include <stdio.h>
2768e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie
2868e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie#include "util/u_inlines.h"
2968e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie#include "util/u_memory.h"
3068e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie#include "util/u_upload_mgr.h"
3168e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie#include "util/u_math.h"
3268e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie
3368e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie#include "r300_screen_buffer.h"
3468e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie
357e752760d410e72cc766691bee207729f28a920aMarek Olšákvoid r300_upload_index_buffer(struct r300_context *r300,
367e752760d410e72cc766691bee207729f28a920aMarek Olšák			      struct pipe_resource **index_buffer,
377e752760d410e72cc766691bee207729f28a920aMarek Olšák			      unsigned index_size, unsigned *start,
38bf469f4edc60bd1c5fd770cb231b8d5ab801427fMarek Olšák			      unsigned count, const uint8_t *ptr)
3968e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie{
407e752760d410e72cc766691bee207729f28a920aMarek Olšák    unsigned index_offset;
417e752760d410e72cc766691bee207729f28a920aMarek Olšák
427e752760d410e72cc766691bee207729f28a920aMarek Olšák    *index_buffer = NULL;
437e752760d410e72cc766691bee207729f28a920aMarek Olšák
44e54cc2c070b30dd9b14bf9aedf93138b660c867fMarek Olšák    u_upload_data(r300->uploader,
4506286110b4fc0ff80ae21bb3d8ff9909db1f5d47Marek Olšák                  0, count * index_size,
467e752760d410e72cc766691bee207729f28a920aMarek Olšák                  ptr + (*start * index_size),
477e752760d410e72cc766691bee207729f28a920aMarek Olšák                  &index_offset,
48f94d390213308d4aca1515c75acc6865ebb45796Marek Olšák                  index_buffer);
497e752760d410e72cc766691bee207729f28a920aMarek Olšák
507e752760d410e72cc766691bee207729f28a920aMarek Olšák    *start = index_offset / index_size;
5168e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie}
5268e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie
53287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwellstatic void r300_buffer_destroy(struct pipe_screen *screen,
54287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell				struct pipe_resource *buf)
5568e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie{
5656ba7e913fef0ea2b1bead582108f9ab3ab8263dMarek Olšák    struct r300_resource *rbuf = r300_resource(buf);
5768e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie
5821b012d3b022c1c55358226f7bcc52fe50078123Marek Olšák    if (rbuf->malloced_buffer)
5921b012d3b022c1c55358226f7bcc52fe50078123Marek Olšák        FREE(rbuf->malloced_buffer);
603eb557778376bcbbc6f25da88ffbaa269607254cMarek Olšák
615862b6ed6196572be0462da913d9e45b4d05f240Marek Olšák    if (rbuf->buf)
62d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák        pb_reference(&rbuf->buf, NULL);
635862b6ed6196572be0462da913d9e45b4d05f240Marek Olšák
64f808984f438b827afff6fdbe52ac52dee8781d03Marek Olšák    FREE(rbuf);
657b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák}
667b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák
677b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšákstatic struct pipe_transfer*
686a46fce14f38adf72925842edf9829c00d1ee800Marek Olšákr300_buffer_get_transfer(struct pipe_context *context,
696a46fce14f38adf72925842edf9829c00d1ee800Marek Olšák                         struct pipe_resource *resource,
706a46fce14f38adf72925842edf9829c00d1ee800Marek Olšák                         unsigned level,
716a46fce14f38adf72925842edf9829c00d1ee800Marek Olšák                         unsigned usage,
726a46fce14f38adf72925842edf9829c00d1ee800Marek Olšák                         const struct pipe_box *box)
737b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák{
747b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák   struct r300_context *r300 = r300_context(context);
757b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák   struct pipe_transfer *transfer =
7680f24c1575688e9cd4a5a811137f43b7e0a661bbMarek Olšák         util_slab_alloc(&r300->pool_transfers);
777b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák
787b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák   transfer->resource = resource;
794c7001462607e6e99e474d6271dd481d3f8f201cRoland Scheidegger   transfer->level = level;
807b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák   transfer->usage = usage;
817b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák   transfer->box = *box;
827b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák   transfer->stride = 0;
834c7001462607e6e99e474d6271dd481d3f8f201cRoland Scheidegger   transfer->layer_stride = 0;
847b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák   transfer->data = NULL;
857b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák
867b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák   /* Note strides are zero, this is ok for buffers, but not for
877b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák    * textures 2d & higher at least.
887b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák    */
897b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák   return transfer;
907b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák}
917b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák
926a46fce14f38adf72925842edf9829c00d1ee800Marek Olšákstatic void r300_buffer_transfer_destroy(struct pipe_context *pipe,
936a46fce14f38adf72925842edf9829c00d1ee800Marek Olšák                                         struct pipe_transfer *transfer)
947b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák{
957b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák   struct r300_context *r300 = r300_context(pipe);
9680f24c1575688e9cd4a5a811137f43b7e0a661bbMarek Olšák   util_slab_free(&r300->pool_transfers, transfer);
9768e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie}
9868e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie
9968e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airliestatic void *
100d3e7dfc1fd7753d6305afb402e432ff45a7c0707Marek Olšákr300_buffer_transfer_map( struct pipe_context *pipe,
101d3e7dfc1fd7753d6305afb402e432ff45a7c0707Marek Olšák			  struct pipe_transfer *transfer )
10268e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie{
103fe3caa91d3f637bf9cf9f9e7adb992aa8c7ef8e4Marek Olšák    struct r300_context *r300 = r300_context(pipe);
104d3e7dfc1fd7753d6305afb402e432ff45a7c0707Marek Olšák    struct r300_screen *r300screen = r300_screen(pipe->screen);
105d35aeff4bb0b03450b2c3c08bd7f84db5bf43283Marek Olšák    struct radeon_winsys *rws = r300screen->rws;
10656ba7e913fef0ea2b1bead582108f9ab3ab8263dMarek Olšák    struct r300_resource *rbuf = r300_resource(transfer->resource);
107d3e7dfc1fd7753d6305afb402e432ff45a7c0707Marek Olšák    uint8_t *map;
108ec4851253bbf7fd7d11c5570f19f9733a885e471Marek Olšák    enum pipe_transfer_usage usage;
10968e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie
11021b012d3b022c1c55358226f7bcc52fe50078123Marek Olšák    if (rbuf->malloced_buffer)
11121b012d3b022c1c55358226f7bcc52fe50078123Marek Olšák        return (uint8_t *) rbuf->malloced_buffer + transfer->box.x;
11268e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie
113ec4851253bbf7fd7d11c5570f19f9733a885e471Marek Olšák    /* Buffers are never used for write, therefore mapping for read can be
114ec4851253bbf7fd7d11c5570f19f9733a885e471Marek Olšák     * unsynchronized. */
115ec4851253bbf7fd7d11c5570f19f9733a885e471Marek Olšák    usage = transfer->usage;
116ec4851253bbf7fd7d11c5570f19f9733a885e471Marek Olšák    if (!(usage & PIPE_TRANSFER_WRITE)) {
117ec4851253bbf7fd7d11c5570f19f9733a885e471Marek Olšák       usage |= PIPE_TRANSFER_UNSYNCHRONIZED;
118ec4851253bbf7fd7d11c5570f19f9733a885e471Marek Olšák    }
119ec4851253bbf7fd7d11c5570f19f9733a885e471Marek Olšák
1200a6120244e66494db070ce875c0a464fbc5b15a1Marek Olšák    map = rws->buffer_map(rbuf->cs_buf, r300->cs, usage);
121d3e7dfc1fd7753d6305afb402e432ff45a7c0707Marek Olšák
122d3e7dfc1fd7753d6305afb402e432ff45a7c0707Marek Olšák    if (map == NULL)
123d3e7dfc1fd7753d6305afb402e432ff45a7c0707Marek Olšák        return NULL;
124d3e7dfc1fd7753d6305afb402e432ff45a7c0707Marek Olšák
125d3e7dfc1fd7753d6305afb402e432ff45a7c0707Marek Olšák    return map + transfer->box.x;
12668e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie}
12768e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie
128d3e7dfc1fd7753d6305afb402e432ff45a7c0707Marek Olšákstatic void r300_buffer_transfer_unmap( struct pipe_context *pipe,
129d3e7dfc1fd7753d6305afb402e432ff45a7c0707Marek Olšák			    struct pipe_transfer *transfer )
13068e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie{
131498e71c156c9292a30081ebd92f519f882ef7fabMarek Olšák    /* no-op */
132287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell}
13368e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie
134d17d03a8dccb4bad25211693320459420409d997Henri Verbeetstatic const struct u_resource_vtbl r300_buffer_vtbl =
135287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell{
13656ba7e913fef0ea2b1bead582108f9ab3ab8263dMarek Olšák   NULL,                               /* get_handle */
1377b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák   r300_buffer_destroy,                /* resource_destroy */
1386a46fce14f38adf72925842edf9829c00d1ee800Marek Olšák   r300_buffer_get_transfer,           /* get_transfer */
1396a46fce14f38adf72925842edf9829c00d1ee800Marek Olšák   r300_buffer_transfer_destroy,       /* transfer_destroy */
1407b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák   r300_buffer_transfer_map,           /* transfer_map */
14156ba7e913fef0ea2b1bead582108f9ab3ab8263dMarek Olšák   NULL,                               /* transfer_flush_region */
1427b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák   r300_buffer_transfer_unmap,         /* transfer_unmap */
143a784d86508a4b609d12ca07986d43005ff2686aeMarek Olšák   NULL   /* transfer_inline_write */
144287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell};
145287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell
146287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwellstruct pipe_resource *r300_buffer_create(struct pipe_screen *screen,
147bb4f5fff0c782f35353e8bfc1b1227e3cc3d5986Marek Olšák					 const struct pipe_resource *templ)
14868e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie{
14968e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie    struct r300_screen *r300screen = r300_screen(screen);
15056ba7e913fef0ea2b1bead582108f9ab3ab8263dMarek Olšák    struct r300_resource *rbuf;
151ee678895e903f3ecbbd95b4584dbfbb127f9d4f0Marek Olšák    unsigned alignment = 16;
15268e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie
153f808984f438b827afff6fdbe52ac52dee8781d03Marek Olšák    rbuf = MALLOC_STRUCT(r300_resource);
154287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell
155a52b3338c6e51421e3836ae210cd98d9c1ec337bMarek Olšák    rbuf->b.b = *templ;
156a52b3338c6e51421e3836ae210cd98d9c1ec337bMarek Olšák    rbuf->b.vtbl = &r300_buffer_vtbl;
157a52b3338c6e51421e3836ae210cd98d9c1ec337bMarek Olšák    pipe_reference_init(&rbuf->b.b.reference, 1);
158a52b3338c6e51421e3836ae210cd98d9c1ec337bMarek Olšák    rbuf->b.b.screen = screen;
15993f4e3cb6c1ca303ee1f5c2a2491a8eff33f2633Marek Olšák    rbuf->domain = RADEON_DOMAIN_GTT;
1607b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák    rbuf->buf = NULL;
16121b012d3b022c1c55358226f7bcc52fe50078123Marek Olšák    rbuf->malloced_buffer = NULL;
162b6b76cbb20b3d9467011231069e23972b98afa49Marek Olšák
16321b012d3b022c1c55358226f7bcc52fe50078123Marek Olšák    /* Alloc constant buffers and SWTCL buffers in RAM. */
16421b012d3b022c1c55358226f7bcc52fe50078123Marek Olšák    if (templ->bind & PIPE_BIND_CONSTANT_BUFFER ||
16521b012d3b022c1c55358226f7bcc52fe50078123Marek Olšák        (!r300screen->caps.has_tcl &&
16621b012d3b022c1c55358226f7bcc52fe50078123Marek Olšák         (templ->bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER)))) {
16721b012d3b022c1c55358226f7bcc52fe50078123Marek Olšák        rbuf->malloced_buffer = MALLOC(templ->width0);
168a52b3338c6e51421e3836ae210cd98d9c1ec337bMarek Olšák        return &rbuf->b.b;
1693eb557778376bcbbc6f25da88ffbaa269607254cMarek Olšák    }
1703eb557778376bcbbc6f25da88ffbaa269607254cMarek Olšák
171ee678895e903f3ecbbd95b4584dbfbb127f9d4f0Marek Olšák    rbuf->buf =
172ee678895e903f3ecbbd95b4584dbfbb127f9d4f0Marek Olšák        r300screen->rws->buffer_create(r300screen->rws,
173a52b3338c6e51421e3836ae210cd98d9c1ec337bMarek Olšák                                       rbuf->b.b.width0, alignment,
174a52b3338c6e51421e3836ae210cd98d9c1ec337bMarek Olšák                                       rbuf->b.b.bind, rbuf->domain);
175ee678895e903f3ecbbd95b4584dbfbb127f9d4f0Marek Olšák    if (!rbuf->buf) {
176f808984f438b827afff6fdbe52ac52dee8781d03Marek Olšák        FREE(rbuf);
1777b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák        return NULL;
1787b31b235d069ab4154bfc4b1eacde6368852aaeeMarek Olšák    }
179287c94ea4987033f9c99a2f91c5750c9083504caKeith Whitwell
180ee678895e903f3ecbbd95b4584dbfbb127f9d4f0Marek Olšák    rbuf->cs_buf =
181ee678895e903f3ecbbd95b4584dbfbb127f9d4f0Marek Olšák        r300screen->rws->buffer_get_cs_handle(rbuf->buf);
182ee678895e903f3ecbbd95b4584dbfbb127f9d4f0Marek Olšák
183a52b3338c6e51421e3836ae210cd98d9c1ec337bMarek Olšák    return &rbuf->b.b;
18468e58a96e80865878e6881dc4d34fcc3ec24eb19Dave Airlie}
185