Home | History | Annotate | Download | only in drm
      1 /**********************************************************
      2  * Copyright 2009 VMware, Inc.  All rights reserved.
      3  *
      4  * Permission is hereby granted, free of charge, to any person
      5  * obtaining a copy of this software and associated documentation
      6  * files (the "Software"), to deal in the Software without
      7  * restriction, including without limitation the rights to use, copy,
      8  * modify, merge, publish, distribute, sublicense, and/or sell copies
      9  * of the Software, and to permit persons to whom the Software is
     10  * furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice shall be
     13  * included in all copies or substantial portions of the Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22  * SOFTWARE.
     23  *
     24  **********************************************************/
     25 
     26 /**
     27  * @file
     28  * SVGA buffer manager for Guest Memory Regions (GMRs).
     29  *
     30  * GMRs are used for pixel and vertex data upload/download to/from the virtual
     31  * SVGA hardware. There is a limited number of GMRs available, and
     32  * creating/destroying them is also a slow operation so we must suballocate
     33  * them.
     34  *
     35  * This file implements a pipebuffer library's buffer manager, so that we can
     36  * use pipepbuffer's suballocation, fencing, and debugging facilities with GMRs.
     37  *
     38  * @author Jose Fonseca <jfonseca (at) vmware.com>
     39  */
     40 
     41 
     42 #include "svga_cmd.h"
     43 
     44 #include "util/u_inlines.h"
     45 #include "util/u_memory.h"
     46 #include "pipebuffer/pb_buffer.h"
     47 #include "pipebuffer/pb_bufmgr.h"
     48 
     49 #include "svga_winsys.h"
     50 
     51 #include "vmw_screen.h"
     52 #include "vmw_buffer.h"
     53 
     54 
     55 struct vmw_gmr_bufmgr;
     56 
     57 
     58 struct vmw_gmr_buffer
     59 {
     60    struct pb_buffer base;
     61 
     62    struct vmw_gmr_bufmgr *mgr;
     63 
     64    struct vmw_region *region;
     65    void *map;
     66 };
     67 
     68 
     69 extern const struct pb_vtbl vmw_gmr_buffer_vtbl;
     70 
     71 
     72 static INLINE struct vmw_gmr_buffer *
     73 vmw_gmr_buffer(struct pb_buffer *buf)
     74 {
     75    assert(buf);
     76    assert(buf->vtbl == &vmw_gmr_buffer_vtbl);
     77    return (struct vmw_gmr_buffer *)buf;
     78 }
     79 
     80 
     81 struct vmw_gmr_bufmgr
     82 {
     83    struct pb_manager base;
     84 
     85    struct vmw_winsys_screen *vws;
     86 };
     87 
     88 
     89 static INLINE struct vmw_gmr_bufmgr *
     90 vmw_gmr_bufmgr(struct pb_manager *mgr)
     91 {
     92    assert(mgr);
     93    return (struct vmw_gmr_bufmgr *)mgr;
     94 }
     95 
     96 
     97 static void
     98 vmw_gmr_buffer_destroy(struct pb_buffer *_buf)
     99 {
    100    struct vmw_gmr_buffer *buf = vmw_gmr_buffer(_buf);
    101 
    102    vmw_ioctl_region_unmap(buf->region);
    103 
    104    vmw_ioctl_region_destroy(buf->region);
    105 
    106    FREE(buf);
    107 }
    108 
    109 
    110 static void *
    111 vmw_gmr_buffer_map(struct pb_buffer *_buf,
    112                    unsigned flags,
    113                    void *flush_ctx)
    114 {
    115    struct vmw_gmr_buffer *buf = vmw_gmr_buffer(_buf);
    116    return buf->map;
    117 }
    118 
    119 
    120 static void
    121 vmw_gmr_buffer_unmap(struct pb_buffer *_buf)
    122 {
    123    /* Do nothing */
    124    (void)_buf;
    125 }
    126 
    127 
    128 static void
    129 vmw_gmr_buffer_get_base_buffer(struct pb_buffer *buf,
    130                            struct pb_buffer **base_buf,
    131                            unsigned *offset)
    132 {
    133    *base_buf = buf;
    134    *offset = 0;
    135 }
    136 
    137 
    138 static enum pipe_error
    139 vmw_gmr_buffer_validate( struct pb_buffer *_buf,
    140                          struct pb_validate *vl,
    141                          unsigned flags )
    142 {
    143    /* Always pinned */
    144    return PIPE_OK;
    145 }
    146 
    147 
    148 static void
    149 vmw_gmr_buffer_fence( struct pb_buffer *_buf,
    150                       struct pipe_fence_handle *fence )
    151 {
    152    /* We don't need to do anything, as the pipebuffer library
    153     * will take care of delaying the destruction of fenced buffers */
    154 }
    155 
    156 
    157 const struct pb_vtbl vmw_gmr_buffer_vtbl = {
    158    vmw_gmr_buffer_destroy,
    159    vmw_gmr_buffer_map,
    160    vmw_gmr_buffer_unmap,
    161    vmw_gmr_buffer_validate,
    162    vmw_gmr_buffer_fence,
    163    vmw_gmr_buffer_get_base_buffer
    164 };
    165 
    166 
    167 static struct pb_buffer *
    168 vmw_gmr_bufmgr_create_buffer(struct pb_manager *_mgr,
    169                          pb_size size,
    170                          const struct pb_desc *desc)
    171 {
    172    struct vmw_gmr_bufmgr *mgr = vmw_gmr_bufmgr(_mgr);
    173    struct vmw_winsys_screen *vws = mgr->vws;
    174    struct vmw_gmr_buffer *buf;
    175 
    176    buf = CALLOC_STRUCT(vmw_gmr_buffer);
    177    if(!buf)
    178       goto error1;
    179 
    180    pipe_reference_init(&buf->base.reference, 1);
    181    buf->base.alignment = desc->alignment;
    182    buf->base.usage = desc->usage;
    183    buf->base.size = size;
    184    buf->base.vtbl = &vmw_gmr_buffer_vtbl;
    185    buf->mgr = mgr;
    186 
    187    buf->region = vmw_ioctl_region_create(vws, size);
    188    if(!buf->region)
    189       goto error2;
    190 
    191    buf->map = vmw_ioctl_region_map(buf->region);
    192    if(!buf->map)
    193       goto error3;
    194 
    195    return &buf->base;
    196 
    197 error3:
    198    vmw_ioctl_region_destroy(buf->region);
    199 error2:
    200    FREE(buf);
    201 error1:
    202    return NULL;
    203 }
    204 
    205 
    206 static void
    207 vmw_gmr_bufmgr_flush(struct pb_manager *mgr)
    208 {
    209    /* No-op */
    210 }
    211 
    212 
    213 static void
    214 vmw_gmr_bufmgr_destroy(struct pb_manager *_mgr)
    215 {
    216    struct vmw_gmr_bufmgr *mgr = vmw_gmr_bufmgr(_mgr);
    217    FREE(mgr);
    218 }
    219 
    220 
    221 struct pb_manager *
    222 vmw_gmr_bufmgr_create(struct vmw_winsys_screen *vws)
    223 {
    224    struct vmw_gmr_bufmgr *mgr;
    225 
    226    mgr = CALLOC_STRUCT(vmw_gmr_bufmgr);
    227    if(!mgr)
    228       return NULL;
    229 
    230    mgr->base.destroy = vmw_gmr_bufmgr_destroy;
    231    mgr->base.create_buffer = vmw_gmr_bufmgr_create_buffer;
    232    mgr->base.flush = vmw_gmr_bufmgr_flush;
    233 
    234    mgr->vws = vws;
    235 
    236    return &mgr->base;
    237 }
    238 
    239 
    240 boolean
    241 vmw_gmr_bufmgr_region_ptr(struct pb_buffer *buf,
    242                           struct SVGAGuestPtr *ptr)
    243 {
    244    struct pb_buffer *base_buf;
    245    unsigned offset = 0;
    246    struct vmw_gmr_buffer *gmr_buf;
    247 
    248    pb_get_base_buffer( buf, &base_buf, &offset );
    249 
    250    gmr_buf = vmw_gmr_buffer(base_buf);
    251    if(!gmr_buf)
    252       return FALSE;
    253 
    254    *ptr = vmw_ioctl_region_ptr(gmr_buf->region);
    255 
    256    ptr->offset += offset;
    257 
    258    return TRUE;
    259 }
    260