Advertisement
Guest User

etna_viv

a guest
Nov 26th, 2015
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 13.30 KB | None | 0 0
  1. /*
  2.  * Copyright (c) 2012-2013 Etnaviv Project
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sub license,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the
  12.  * next paragraph) shall be included in all copies or substantial portions
  13.  * of the Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21.  * DEALINGS IN THE SOFTWARE.
  22.  */
  23. #include <etnaviv/etna_bo.h>
  24. #include <etnaviv/etna.h>
  25. #include <etnaviv/etna_queue.h>
  26.  
  27. #include <string.h>
  28. #include <stdlib.h>
  29. #include <stdio.h>
  30. #include <sys/ioctl.h>
  31. #include <sys/mman.h>
  32. #include <linux/fb.h>
  33.  
  34. #include "gc_abi.h"
  35.  
  36. //#define DEBUG
  37. #define ETNA_VIDMEM_ALIGNMENT (0x40)
  38.  
  39. enum etna_bo_type {
  40.     ETNA_BO_TYPE_VIDMEM,    /* Main vidmem */
  41.     ETNA_BO_TYPE_VIDMEM_EXTERNAL, /* Main vidmem, external handle */
  42.     ETNA_BO_TYPE_USERMEM,   /* Mapped user memory */
  43.     ETNA_BO_TYPE_CONTIGUOUS,/* Contiguous memory */
  44.     ETNA_BO_TYPE_PHYSICAL,  /* Mmap-ed physical memory */
  45.     ETNA_BO_TYPE_DMABUF     /* dmabuf memory */
  46. };
  47.  
  48. /* Structure describing a block of video or user memory */
  49. struct etna_bo {
  50.     enum etna_bo_type bo_type;
  51.     size_t size;
  52.     enum viv_surf_type type;
  53.     viv_node_t node;
  54.     viv_addr_t address;
  55.     void *logical;
  56.     viv_usermem_t usermem_info;
  57. };
  58.  
  59. #ifdef DEBUG
  60. static const char *etna_bo_surf_type(struct etna_bo *mem)
  61. {
  62.     const char *ret = NULL;
  63.  
  64.     switch (mem->type) {
  65.         case VIV_SURF_UNKNOWN:
  66.             ret = "VIV_SURF_UNKNOWN";
  67.         break;
  68.  
  69.         case VIV_SURF_INDEX:
  70.             ret = "VIV_SURF_INDEX";
  71.         break;
  72.  
  73.         case VIV_SURF_VERTEX:
  74.             ret = "VIV_SURF_VERTEX";
  75.         break;
  76.  
  77.         case VIV_SURF_TEXTURE:
  78.             ret = "VIV_SURF_TEXTURE";
  79.         break;
  80.  
  81.         case VIV_SURF_RENDER_TARGET:
  82.             ret = "VIV_SURF_RENDER_TARGET";
  83.         break;
  84.  
  85.         case VIV_SURF_DEPTH:
  86.             ret = "VIV_SURF_DEPTH";
  87.         break;
  88.  
  89.         case VIV_SURF_BITMAP:
  90.             ret = "VIV_SURF_BITMAP";
  91.         break;
  92.  
  93.         case VIV_SURF_TILE_STATUS:
  94.             ret = "VIV_SURF_TILE_STATUS";
  95.         break;
  96.  
  97.         case VIV_SURF_IMAGE:
  98.             ret = "VIV_SURF_IMAGE";
  99.         break;
  100.  
  101.         case VIV_SURF_MASK:
  102.             ret = "VIV_SURF_MASK";
  103.         break;
  104.  
  105.         case VIV_SURF_SCISSOR:
  106.             ret = "VIV_SURF_SCISSOR";
  107.         break;
  108.  
  109.         case VIV_SURF_HIERARCHICAL_DEPTH:
  110.             ret = "VIV_SURF_HIERARCHICAL_DEPTH";
  111.         break;
  112.  
  113.         default:
  114.            ret = "hmmmm?";
  115.         break;
  116.     }
  117.     return ret;
  118. }
  119. #endif
  120.  
  121. /* Lock (map) memory into both CPU and GPU memory space. */
  122. static int etna_bo_lock(struct viv_conn *conn, struct etna_bo *mem)
  123. {
  124.     if(mem == NULL) return ETNA_INVALID_ADDR;
  125.     if(mem->logical != NULL) return ETNA_ALREADY_LOCKED;
  126.  
  127.     if(viv_lock_vidmem(conn, mem->node, &mem->address, &mem->logical)!=0)
  128.     {
  129. #ifdef DEBUG
  130.         fprintf(stderr, "Error locking render target memory\n");
  131. #endif
  132.         return ETNA_INTERNAL_ERROR;
  133.     }
  134. #ifdef DEBUG
  135.     fprintf(stderr, "Locked: phys=%08x log=%08x\n", (uint32_t)mem->address, (uint32_t)mem->logical);
  136. #endif
  137.  
  138.     return ETNA_OK;
  139. }
  140.  
  141. /* Unlock memory from both CPU and GPU memory space */
  142. static int etna_bo_unlock(struct viv_conn *conn, struct etna_bo *mem, struct etna_queue *queue)
  143. {
  144.     if(mem == NULL) return ETNA_INVALID_ADDR;
  145.     int async = 0;
  146.     /* Unlocking video memory seems to be a two-step process. First try it synchronously
  147.      * then the kernel can request an asynchronous component. Just queueing it asynchronously
  148.      * in the first place will not free the virtual memory on v4 */
  149.     if(viv_unlock_vidmem(conn, mem->node, mem->type, false, &async) != ETNA_OK)
  150.     {
  151.         return ETNA_INTERNAL_ERROR;
  152.     }
  153.     if(async)
  154.     {
  155.         if(queue)
  156.         {
  157.             /* If a queue is passed, add the async part at the end of the queue, to be submitted
  158.              * with next flush.
  159.              */
  160.             if(etna_queue_unlock_vidmem(queue, mem->node, mem->type) != ETNA_OK)
  161.             {
  162.                 return ETNA_INTERNAL_ERROR;
  163.             }
  164.         } else { /* No queue, need to submit async part directly as event */
  165.             if(viv_unlock_vidmem(conn, mem->node, mem->type, true, &async) != ETNA_OK)
  166.             {
  167.                 return ETNA_INTERNAL_ERROR;
  168.             }
  169.         }
  170.     }
  171.     mem->logical = NULL;
  172.     mem->address = 0;
  173.     return ETNA_OK;
  174. }
  175.  
  176. struct etna_bo* etna_bo_new(struct viv_conn *conn, size_t bytes, uint32_t flags)
  177. {
  178.     struct etna_bo *mem = ETNA_CALLOC_STRUCT(etna_bo);
  179.  
  180.     //DKS - debugging
  181.     //if(mem == NULL) return NULL;
  182.     if(mem == NULL) {
  183.         fprintf(stderr, "Error: mem==NULL in etna_bo_new() in %s, line %d\n", __FILE__, __LINE__ );
  184.         return NULL;
  185.     }
  186.  
  187.     if((flags & DRM_ETNA_GEM_TYPE_MASK) == DRM_ETNA_GEM_TYPE_CMD)
  188.     {
  189.         mem->bo_type = ETNA_BO_TYPE_CONTIGUOUS;
  190.         /* Command buffers must be allocated with viv_alloc_contiguous */
  191.         if(viv_alloc_contiguous(conn, bytes,
  192.                     &mem->address,
  193.                     &mem->logical,
  194.                     &mem->size)!=0)
  195.         {
  196.             //DKS - debugging
  197.             fprintf(stderr, "Error: viv_alloc_contiguous() returned non-zero etna_bo_new() in %s, line %d\n", __FILE__, __LINE__ );
  198.  
  199.             ETNA_FREE(mem);
  200.             return NULL;
  201.         }
  202.     } else {
  203.         enum viv_surf_type type = VIV_SURF_UNKNOWN;
  204.         enum viv_pool pool = VIV_POOL_DEFAULT;
  205.         /* Convert GEM bits to surface type */
  206.         switch(flags & DRM_ETNA_GEM_TYPE_MASK)
  207.         {
  208.         case DRM_ETNA_GEM_TYPE_IDX: type = VIV_SURF_INDEX; break;
  209.         case DRM_ETNA_GEM_TYPE_VTX: type = VIV_SURF_VERTEX; break;
  210.         case DRM_ETNA_GEM_TYPE_TEX: type = VIV_SURF_TEXTURE; break;
  211.         case DRM_ETNA_GEM_TYPE_RT:  type = VIV_SURF_RENDER_TARGET; break;
  212.         case DRM_ETNA_GEM_TYPE_ZS:  type = VIV_SURF_DEPTH; break;
  213.         case DRM_ETNA_GEM_TYPE_HZ:  type = VIV_SURF_HIERARCHICAL_DEPTH; break;
  214.         case DRM_ETNA_GEM_TYPE_BMP: type = VIV_SURF_BITMAP; break;
  215.         case DRM_ETNA_GEM_TYPE_TS:  type = VIV_SURF_TILE_STATUS; break;
  216.         default: /* Invalid type */
  217.             //DKS - debugging
  218.             fprintf(stderr, "Error: invalid surf type in etna_bo_new() in %s, line %d\n", __FILE__, __LINE__ );
  219.  
  220.             ETNA_FREE(mem);
  221.             return NULL;
  222.             break;
  223.         }
  224.  
  225.         mem->bo_type = ETNA_BO_TYPE_VIDMEM;
  226.         mem->type = type;
  227.         if(viv_alloc_linear_vidmem(conn, bytes, ETNA_VIDMEM_ALIGNMENT, type, pool, &mem->node, &mem->size)!=0)
  228.         {
  229. #ifdef DEBUG
  230.             //DKS - debugging
  231.             //fprintf(stderr, "Error allocating memory\n");
  232.  
  233.             fprintf(stderr, "Error: allocating memory in etna_bo_new() in %s, line %d\n", __FILE__, __LINE__ );
  234. #endif
  235.             return NULL;
  236.         }
  237. #ifdef DEBUG
  238.         fprintf(stderr, "Allocated: type:%s mem=%p node=%08x size=%08x\n", etna_bo_surf_type(mem), mem, (uint32_t)mem->node, mem->size);
  239. #endif
  240.         int status = etna_bo_lock(conn, mem);
  241.         if(status != ETNA_OK)
  242.         {
  243.             //DKS - debugging
  244.             fprintf(stderr, "Error returned from etna_bo_lock() in etna_bo_new() in %s, line %d\n", __FILE__, __LINE__ );
  245.  
  246.             etna_bo_del(conn, mem, NULL);
  247.             return NULL;
  248.         }
  249.     }
  250.     return mem;
  251. }
  252.  
  253. struct etna_bo *etna_bo_from_usermem_prot(struct viv_conn *conn, void *memory, size_t size, int prot)
  254. {
  255.     struct etna_bo *mem = ETNA_CALLOC_STRUCT(etna_bo);
  256.     if(mem == NULL) return NULL;
  257.  
  258.     mem->bo_type = ETNA_BO_TYPE_USERMEM;
  259.     mem->logical = memory;
  260.     mem->size = size;
  261.  
  262.     if(viv_map_user_memory_prot(conn, memory, size, prot, &mem->usermem_info, &mem->address)!=0)
  263.     {
  264.         ETNA_FREE(mem);
  265.         return NULL;
  266.     }
  267.  
  268.     return mem;
  269. }
  270.  
  271. struct etna_bo *etna_bo_from_usermem(struct viv_conn *conn, void *memory, size_t size)
  272. {
  273.     struct etna_bo *mem = ETNA_CALLOC_STRUCT(etna_bo);
  274.     if(mem == NULL) return NULL;
  275.  
  276.     mem->bo_type = ETNA_BO_TYPE_USERMEM;
  277.     mem->logical = memory;
  278.     mem->size = size;
  279.  
  280.     if(viv_map_user_memory(conn, memory, size, &mem->usermem_info, &mem->address)!=0)
  281.     {
  282.         ETNA_FREE(mem);
  283.         return NULL;
  284.     }
  285.  
  286.     return mem;
  287. }
  288.  
  289. struct etna_bo *etna_bo_from_fbdev(struct viv_conn *conn, int fd, size_t offset, size_t size)
  290. {
  291.     struct fb_fix_screeninfo finfo;
  292.     struct etna_bo *mem = ETNA_CALLOC_STRUCT(etna_bo);
  293.     if(mem == NULL) return NULL;
  294.  
  295.     if(ioctl(fd, FBIOGET_FSCREENINFO, &finfo))
  296.         goto error;
  297.  
  298.     mem->bo_type = ETNA_BO_TYPE_PHYSICAL;
  299.     if((mem->logical = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset)) == NULL)
  300.         goto error;
  301.     mem->address = finfo.smem_start + offset;
  302.     mem->size = size;
  303.     return mem;
  304. error:
  305.     ETNA_FREE(mem);
  306.     return NULL;
  307. }
  308.  
  309. struct etna_bo *etna_bo_from_name(struct viv_conn *conn, uint32_t name)
  310. {
  311.     struct etna_bo *mem = ETNA_CALLOC_STRUCT(etna_bo);
  312.     if(mem == NULL) return NULL;
  313.  
  314.     mem->bo_type = ETNA_BO_TYPE_VIDMEM_EXTERNAL;
  315.     mem->node = (viv_node_t)name;
  316.  
  317.     /* Lock to this address space */
  318.     int status = etna_bo_lock(conn, mem);
  319.     if(status != ETNA_OK)
  320.     {
  321.         free(mem);
  322.         return NULL;
  323.     }
  324.     return mem;
  325. }
  326.  
  327. struct etna_bo *etna_bo_from_dmabuf(struct viv_conn *conn, int fd, int prot)
  328. {
  329.     struct etna_bo *mem = ETNA_CALLOC_STRUCT(etna_bo);
  330.     if(mem == NULL) return NULL;
  331.  
  332.     mem->bo_type = ETNA_BO_TYPE_DMABUF;
  333.  
  334.     if(viv_map_dmabuf(conn, fd, &mem->usermem_info, &mem->address, prot)!=0)
  335.     {
  336.         ETNA_FREE(mem);
  337.         return NULL;
  338.     }
  339.  
  340.     return mem;
  341. }
  342.  
  343. struct etna_bo *etna_bo_ref(struct etna_bo *bo)
  344. {
  345.     /* TODO */
  346.     return bo;
  347. }
  348.  
  349. int etna_bo_del(struct viv_conn *conn, struct etna_bo *mem, struct etna_queue *queue)
  350. {
  351.     int rv = ETNA_OK;
  352.     if(mem == NULL) return ETNA_OK;
  353.     switch(mem->bo_type)
  354.     {
  355.     case ETNA_BO_TYPE_VIDMEM:
  356.         if(mem->logical != NULL)
  357.         {
  358.             if((rv = etna_bo_unlock(conn, mem, queue)) != ETNA_OK)
  359.             {
  360.                 fprintf(stderr, "etna: Warning: could not unlock memory\n");
  361.             }
  362.         }
  363.         if(queue)
  364.         {
  365.             if((rv = etna_queue_free_vidmem(queue, mem->node)) != ETNA_OK)
  366.             {
  367.                 fprintf(stderr, "etna: Warning: could not queue free video memory\n");
  368.             }
  369.         } else {
  370.             if((rv = viv_free_vidmem(conn, mem->node, true)) != ETNA_OK)
  371.             {
  372.                 fprintf(stderr, "etna: Warning: could not free video memory\n");
  373.             }
  374.         }
  375.         break;
  376.     case ETNA_BO_TYPE_VIDMEM_EXTERNAL:
  377.         if((rv = etna_bo_unlock(conn, mem, queue)) != ETNA_OK)
  378.         {
  379.             fprintf(stderr, "etna: Warning: could not unlock memory\n");
  380.         }
  381.         break;
  382.     case ETNA_BO_TYPE_USERMEM:
  383.         if(queue)
  384.         {
  385.             rv = etna_queue_unmap_user_memory(queue, mem->logical, mem->size, mem->usermem_info, mem->address);
  386.         } else
  387.         {
  388.             rv = viv_unmap_user_memory(conn, mem->logical, mem->size, mem->usermem_info, mem->address);
  389.         }
  390.         break;
  391.     case ETNA_BO_TYPE_CONTIGUOUS:
  392.         if(queue)
  393.         {
  394.             rv = etna_queue_free_contiguous(queue, mem->size, mem->address, mem->logical);
  395.         } else {
  396.             rv = viv_free_contiguous(conn, mem->size, mem->address, mem->logical);
  397.         }
  398.         break;
  399.     case ETNA_BO_TYPE_PHYSICAL:
  400.         if(munmap(mem->logical, mem->size) < 0)
  401.         {
  402.             rv = ETNA_OUT_OF_MEMORY;
  403.         }
  404.         break;
  405.     case ETNA_BO_TYPE_DMABUF:
  406.         if(queue)
  407.         {
  408.             rv = etna_queue_unmap_user_memory(queue, (void *)1, 1, mem->usermem_info, mem->address);
  409.         } else {
  410.             rv = viv_unmap_user_memory(conn, (void *)1, 1, mem->usermem_info, mem->address);
  411.         }
  412.         break;
  413.     }
  414.     ETNA_FREE(mem);
  415.     return rv;
  416. }
  417.  
  418. int etna_bo_get_name(struct etna_bo *bo, uint32_t *name)
  419. {
  420.     *name = (uint32_t)bo->node;
  421.     return 0;
  422. }
  423.  
  424. uint32_t etna_bo_handle(struct etna_bo *bo)
  425. {
  426.     return (uint32_t)bo->node;
  427. }
  428.  
  429. uint32_t etna_bo_size(struct etna_bo *bo)
  430. {
  431.     return bo->size;
  432. }
  433.  
  434. void *etna_bo_map(struct etna_bo *bo)
  435. {
  436.     return bo->logical;
  437. }
  438.  
  439. int etna_bo_cpu_prep(struct etna_bo *bo, struct etna_ctx *pipe, uint32_t op)
  440. {
  441.     /* TODO */
  442.     return 0;
  443. }
  444.  
  445. void etna_bo_cpu_fini(struct etna_bo *bo)
  446. {
  447.     /* No-op */
  448. }
  449.  
  450. uint32_t etna_bo_gpu_address(struct etna_bo *bo)
  451. {
  452.     return bo->address;
  453. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement