Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.  * This file implements the SVGA interface into this winsys, defined
  29.  * in drivers/svga/svga_winsys.h.
  30.  *
  31.  * @author Keith Whitwell
  32.  * @author Jose Fonseca
  33.  */
  34.  
  35.  
  36. #include "svga_cmd.h"
  37. #include "svga3d_caps.h"
  38.  
  39. #include "util/u_inlines.h"
  40. #include "util/u_math.h"
  41. #include "util/u_memory.h"
  42. #include "pipebuffer/pb_buffer.h"
  43. #include "pipebuffer/pb_bufmgr.h"
  44. #include "svga_winsys.h"
  45. #include "vmw_context.h"
  46. #include "vmw_screen.h"
  47. #include "vmw_surface.h"
  48. #include "vmw_buffer.h"
  49. #include "vmw_fence.h"
  50. #include "vmw_shader.h"
  51. #include "svga3d_surfacedefs.h"
  52.  
  53. /**
  54.  * Try to get a surface backing buffer from the cache
  55.  * if it's this size or smaller.
  56.  */
  57. #define VMW_TRY_CACHED_SIZE (2*1024*1024)
  58.  
  59. static struct svga_winsys_buffer *
  60. vmw_svga_winsys_buffer_create(struct svga_winsys_screen *sws,
  61.                               unsigned alignment,
  62.                               unsigned usage,
  63.                               unsigned size)
  64. {
  65.    struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
  66.    struct vmw_buffer_desc desc;
  67.    struct pb_manager *provider;
  68.    struct pb_buffer *buffer;
  69.  
  70.    memset(&desc, 0, sizeof desc);
  71.    desc.pb_desc.alignment = alignment;
  72.    desc.pb_desc.usage = usage;
  73.  
  74.    if (usage == SVGA_BUFFER_USAGE_PINNED) {
  75.       if (vws->pools.query_fenced == NULL && !vmw_query_pools_init(vws))
  76.          return NULL;
  77.       provider = vws->pools.query_fenced;
  78.    } else if (usage == SVGA_BUFFER_USAGE_SHADER) {
  79.       provider = vws->pools.mob_shader_slab_fenced;
  80.    } else
  81.       provider = vws->pools.gmr_fenced;
  82.  
  83.    assert(provider);
  84.    buffer = provider->create_buffer(provider, size, &desc.pb_desc);
  85.  
  86.    if(!buffer && provider == vws->pools.gmr_fenced) {
  87.  
  88.       assert(provider);
  89.       provider = vws->pools.gmr_slab_fenced;
  90.       buffer = provider->create_buffer(provider, size, &desc.pb_desc);
  91.    }
  92.  
  93.    if (!buffer)
  94.       return NULL;
  95.  
  96.    return vmw_svga_winsys_buffer_wrap(buffer);
  97. }
  98.  
  99.  
  100. static void
  101. vmw_svga_winsys_fence_reference(struct svga_winsys_screen *sws,
  102.                                 struct pipe_fence_handle **pdst,
  103.                                 struct pipe_fence_handle *src)
  104. {
  105.     struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
  106.  
  107.     vmw_fence_reference(vws, pdst, src);
  108. }
  109.  
  110.  
  111. static int
  112. vmw_svga_winsys_fence_signalled(struct svga_winsys_screen *sws,
  113.                                 struct pipe_fence_handle *fence,
  114.                                 unsigned flag)
  115. {
  116.    struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
  117.  
  118.    return vmw_fence_signalled(vws, fence, flag);
  119. }
  120.  
  121.  
  122. static int
  123. vmw_svga_winsys_fence_finish(struct svga_winsys_screen *sws,
  124.                              struct pipe_fence_handle *fence,
  125.                              unsigned flag)
  126. {
  127.    struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
  128.  
  129.    return vmw_fence_finish(vws, fence, flag);
  130. }
  131.  
  132.  
  133.  
  134. static struct svga_winsys_surface *
  135. vmw_svga_winsys_surface_create(struct svga_winsys_screen *sws,
  136.                                SVGA3dSurfaceFlags flags,
  137.                                SVGA3dSurfaceFormat format,
  138.                                unsigned usage,
  139.                                SVGA3dSize size,
  140.                                uint32 numFaces,
  141.                                uint32 numMipLevels)
  142. {
  143.    struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
  144.    struct vmw_svga_winsys_surface *surface;
  145.    struct vmw_buffer_desc desc;
  146.    struct pb_manager *provider;
  147.    uint32_t buffer_size;
  148.  
  149.  
  150.    memset(&desc, 0, sizeof(desc));
  151.    surface = CALLOC_STRUCT(vmw_svga_winsys_surface);
  152.    if(!surface)
  153.       goto no_surface;
  154.  
  155.    pipe_reference_init(&surface->refcnt, 1);
  156.    p_atomic_set(&surface->validated, 0);
  157.    surface->screen = vws;
  158.    pipe_mutex_init(surface->mutex);
  159.    surface->shared = !!(usage & SVGA_SURFACE_USAGE_SHARED);
  160.    provider = (surface->shared) ? vws->pools.gmr : vws->pools.mob_fenced;
  161.  
  162.    /*
  163.     * Used for the backing buffer GB surfaces, and to approximate
  164.     * when to flush on non-GB hosts.
  165.     */
  166.    buffer_size = svga3dsurface_get_serialized_size(format, size, numMipLevels, (numFaces == 6));
  167.    if (buffer_size > vws->ioctl.max_texture_size) {
  168.       goto no_sid;
  169.    }
  170.  
  171.    if (sws->have_gb_objects) {
  172.       SVGAGuestPtr ptr = {0,0};
  173.  
  174.       /*
  175.        * If the backing buffer size is small enough, try to allocate a
  176.        * buffer out of the buffer cache. Otherwise, let the kernel allocate
  177.        * a suitable buffer for us.
  178.        */
  179.       if (buffer_size < VMW_TRY_CACHED_SIZE && !surface->shared) {
  180.          struct pb_buffer *pb_buf;
  181.  
  182.          surface->size = buffer_size;
  183.          desc.pb_desc.alignment = 4096;
  184.          desc.pb_desc.usage = 0;
  185.          pb_buf = provider->create_buffer(provider, buffer_size, &desc.pb_desc);
  186.          surface->buf = vmw_svga_winsys_buffer_wrap(pb_buf);
  187.          if (surface->buf && !vmw_gmr_bufmgr_region_ptr(pb_buf, &ptr))
  188.             assert(0);
  189.       }
  190.  
  191.       surface->sid = vmw_ioctl_gb_surface_create(vws, flags, format, usage,
  192.                                                  size, numFaces,
  193.                                                  numMipLevels, ptr.gmrId,
  194.                                                  surface->buf ? NULL :
  195.                                                  &desc.region);
  196.  
  197.       if (surface->sid == SVGA3D_INVALID_ID && surface->buf) {
  198.  
  199.          /*
  200.           * Kernel refused to allocate a surface for us.
  201.           * Perhaps something was wrong with our buffer?
  202.           * This is really a guard against future new size requirements
  203.           * on the backing buffers.
  204.           */
  205.          vmw_svga_winsys_buffer_destroy(sws, surface->buf);
  206.          surface->buf = NULL;
  207.          surface->sid = vmw_ioctl_gb_surface_create(vws, flags, format, usage,
  208.                                                     size, numFaces,
  209.                                                     numMipLevels, 0,
  210.                                                     &desc.region);
  211.          if (surface->sid == SVGA3D_INVALID_ID)
  212.             goto no_sid;
  213.       }
  214.  
  215.       /*
  216.        * If the kernel created the buffer for us, wrap it into a
  217.        * vmw_svga_winsys_buffer.
  218.        */
  219.       if (surface->buf == NULL) {
  220.          struct pb_buffer *pb_buf;
  221.  
  222.          surface->size = vmw_region_size(desc.region);
  223.          desc.pb_desc.alignment = 4096;
  224.          desc.pb_desc.usage = VMW_BUFFER_USAGE_SHARED;
  225.          pb_buf = provider->create_buffer(provider, surface->size,
  226.                                           &desc.pb_desc);
  227.          surface->buf = vmw_svga_winsys_buffer_wrap(pb_buf);
  228.          if (surface->buf == NULL) {
  229.             vmw_ioctl_region_destroy(desc.region);
  230.             vmw_ioctl_surface_destroy(vws, surface->sid);
  231.             goto no_sid;
  232.          }
  233.       }
  234.    } else {
  235.       surface->sid = vmw_ioctl_surface_create(vws, flags, format, usage,
  236.                                               size, numFaces, numMipLevels);
  237.       if(surface->sid == SVGA3D_INVALID_ID)
  238.          goto no_sid;
  239.  
  240.       /* Best estimate for surface size, used for early flushing. */
  241.       surface->size = buffer_size;
  242.       surface->buf = NULL;
  243.    }      
  244.  
  245.    return svga_winsys_surface(surface);
  246.  
  247. no_sid:
  248.    if (surface->buf)
  249.       vmw_svga_winsys_buffer_destroy(sws, surface->buf);
  250.  
  251.    FREE(surface);
  252. no_surface:
  253.    return NULL;
  254. }
  255.  
  256. static boolean
  257. vmw_svga_winsys_surface_can_create(struct svga_winsys_screen *sws,
  258.                                SVGA3dSurfaceFormat format,
  259.                                SVGA3dSize size,
  260.                                uint32 numFaces,
  261.                                uint32 numMipLevels)
  262. {
  263.    struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
  264.    uint32_t buffer_size;
  265.  
  266.    buffer_size = svga3dsurface_get_serialized_size(format, size,
  267.                                                    numMipLevels,
  268.                                                    (numFaces == 6));
  269.    if (buffer_size > vws->ioctl.max_texture_size) {
  270.         return FALSE;
  271.    }
  272.    return TRUE;
  273. }
  274.  
  275.  
  276. static boolean
  277. vmw_svga_winsys_surface_is_flushed(struct svga_winsys_screen *sws,
  278.                                    struct svga_winsys_surface *surface)
  279. {
  280.    struct vmw_svga_winsys_surface *vsurf = vmw_svga_winsys_surface(surface);
  281.    return (p_atomic_read(&vsurf->validated) == 0);
  282. }
  283.  
  284.  
  285. static void
  286. vmw_svga_winsys_surface_ref(struct svga_winsys_screen *sws,
  287.                             struct svga_winsys_surface **pDst,
  288.                             struct svga_winsys_surface *src)
  289. {
  290.    struct vmw_svga_winsys_surface *d_vsurf = vmw_svga_winsys_surface(*pDst);
  291.    struct vmw_svga_winsys_surface *s_vsurf = vmw_svga_winsys_surface(src);
  292.  
  293.    vmw_svga_winsys_surface_reference(&d_vsurf, s_vsurf);
  294.    *pDst = svga_winsys_surface(d_vsurf);
  295. }
  296.  
  297.  
  298. static void
  299. vmw_svga_winsys_destroy(struct svga_winsys_screen *sws)
  300. {
  301.    struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
  302.  
  303.    vmw_winsys_destroy(vws);
  304. }
  305.  
  306.  
  307. static SVGA3dHardwareVersion
  308. vmw_svga_winsys_get_hw_version(struct svga_winsys_screen *sws)
  309. {
  310.    struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
  311.  
  312.    if (sws->have_gb_objects)
  313.       return SVGA3D_HWVERSION_WS8_B1;
  314.  
  315.    return (SVGA3dHardwareVersion) vws->ioctl.hwversion;
  316. }
  317.  
  318.  
  319. static boolean
  320. vmw_svga_winsys_get_cap(struct svga_winsys_screen *sws,
  321.                         SVGA3dDevCapIndex index,
  322.                         SVGA3dDevCapResult *result)
  323. {  
  324.    struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
  325.  
  326.    if (index > vws->ioctl.num_cap_3d || !vws->ioctl.cap_3d[index].has_cap)      
  327.       return FALSE;
  328.  
  329.    *result = vws->ioctl.cap_3d[index].result;
  330.    return TRUE;
  331. }
  332.  
  333. static struct svga_winsys_gb_shader *
  334. vmw_svga_winsys_shader_create(struct svga_winsys_screen *sws,
  335.                               SVGA3dShaderType type,
  336.                               const uint32 *bytecode,
  337.                               uint32 bytecodeLen)
  338. {
  339.    struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
  340.    struct vmw_svga_winsys_shader *shader;
  341.    void *code;
  342.  
  343.    shader = CALLOC_STRUCT(vmw_svga_winsys_shader);
  344.    if(!shader)
  345.       goto out_no_shader;
  346.  
  347.    pipe_reference_init(&shader->refcnt, 1);
  348.    p_atomic_set(&shader->validated, 0);
  349.    shader->screen = vws;
  350.    shader->buf = vmw_svga_winsys_buffer_create(sws, 64,
  351.                                                SVGA_BUFFER_USAGE_SHADER,
  352.                                                bytecodeLen);
  353.    if (!shader->buf)
  354.       goto out_no_buf;
  355.  
  356.    code = vmw_svga_winsys_buffer_map(sws, shader->buf, PIPE_TRANSFER_WRITE);
  357.    if (!code)
  358.       goto out_no_buf;
  359.  
  360.    memcpy(code, bytecode, bytecodeLen);
  361.    vmw_svga_winsys_buffer_unmap(sws, shader->buf);
  362.  
  363.    shader->shid = vmw_ioctl_shader_create(vws, type, bytecodeLen);
  364.    if(shader->shid == SVGA3D_INVALID_ID)
  365.       goto out_no_shid;
  366.  
  367.    return svga_winsys_shader(shader);
  368.  
  369. out_no_shid:
  370.    vmw_svga_winsys_buffer_destroy(sws, shader->buf);
  371. out_no_buf:
  372.    FREE(shader);
  373. out_no_shader:
  374.    return NULL;
  375. }
  376.  
  377. static void
  378. vmw_svga_winsys_shader_destroy(struct svga_winsys_screen *sws,
  379.                                struct svga_winsys_gb_shader *shader)
  380. {
  381.    struct vmw_svga_winsys_shader *d_shader =
  382.       vmw_svga_winsys_shader(shader);
  383.  
  384.    vmw_svga_winsys_shader_reference(&d_shader, NULL);
  385. }
  386.  
  387. boolean
  388. vmw_winsys_screen_init_svga(struct vmw_winsys_screen *vws)
  389. {
  390.    vws->base.destroy = vmw_svga_winsys_destroy;
  391.    vws->base.get_hw_version = vmw_svga_winsys_get_hw_version;
  392.    vws->base.get_cap = vmw_svga_winsys_get_cap;
  393.    vws->base.context_create = vmw_svga_winsys_context_create;
  394.    vws->base.surface_create = vmw_svga_winsys_surface_create;
  395.    vws->base.surface_is_flushed = vmw_svga_winsys_surface_is_flushed;
  396.    vws->base.surface_reference = vmw_svga_winsys_surface_ref;
  397.    vws->base.surface_can_create = vmw_svga_winsys_surface_can_create;
  398.    vws->base.buffer_create = vmw_svga_winsys_buffer_create;
  399.    vws->base.buffer_map = vmw_svga_winsys_buffer_map;
  400.    vws->base.buffer_unmap = vmw_svga_winsys_buffer_unmap;
  401.    vws->base.buffer_destroy = vmw_svga_winsys_buffer_destroy;
  402.    vws->base.fence_reference = vmw_svga_winsys_fence_reference;
  403.    vws->base.fence_signalled = vmw_svga_winsys_fence_signalled;
  404.    vws->base.shader_create = vmw_svga_winsys_shader_create;
  405.    vws->base.shader_destroy = vmw_svga_winsys_shader_destroy;
  406.    vws->base.fence_finish = vmw_svga_winsys_fence_finish;
  407.  
  408.    return TRUE;
  409. }
  410.  
  411.  
  412.