Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  *
  4.  * Copyright (C) 2010 LunarG Inc.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the "Software"),
  8.  * to deal in the Software without restriction, including without limitation
  9.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10.  * and/or sell copies of the Software, and to permit persons to whom the
  11.  * Software is furnished to do so, subject to the following conditions:
  12.  *
  13.  * The above copyright notice and this permission notice shall be included
  14.  * in all copies or substantial portions of the Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22.  * DEALINGS IN THE SOFTWARE.
  23.  *
  24.  * Authors:
  25.  *    Chia-I Wu <olv@lunarg.com>
  26.  */
  27.  
  28. #include "pipe/p_screen.h"
  29. #include "util/u_memory.h"
  30. #include "util/u_rect.h"
  31. #include "util/u_inlines.h"
  32. #include "eglcurrent.h"
  33. #include "egllog.h"
  34.  
  35. #include "native.h"
  36. #include "egl_g3d.h"
  37. #include "egl_g3d_image.h"
  38.  
  39. /**
  40.  * Reference and return the front left buffer of the native pixmap.
  41.  */
  42. static struct pipe_resource *
  43. egl_g3d_reference_native_pixmap(_EGLDisplay *dpy, EGLNativePixmapType pix)
  44. {
  45.    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
  46.    struct native_surface *nsurf;
  47.    struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS];
  48.    enum native_attachment natt;
  49.  
  50.    nsurf = gdpy->native->create_pixmap_surface(gdpy->native, pix, NULL);
  51.    if (!nsurf)
  52.       return NULL;
  53.  
  54.    natt = NATIVE_ATTACHMENT_FRONT_LEFT;
  55.    if (!nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL))
  56.       textures[natt] = NULL;
  57.  
  58.    nsurf->destroy(nsurf);
  59.  
  60.    return textures[natt];
  61. }
  62.  
  63. #ifdef EGL_MESA_drm_image
  64.  
  65. static struct pipe_resource *
  66. egl_g3d_create_drm_buffer(_EGLDisplay *dpy, _EGLImage *img,
  67.                           const EGLint *attribs)
  68. {
  69.    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
  70.    struct pipe_screen *screen = gdpy->native->screen;
  71.    struct pipe_resource templ;
  72.    _EGLImageAttribs attrs;
  73.    EGLint format, valid_use;
  74.  
  75.    if (_eglParseImageAttribList(&attrs, dpy, attribs) != EGL_SUCCESS)
  76.       return NULL;
  77.  
  78.    if (attrs.Width <= 0 || attrs.Height <= 0) {
  79.       _eglLog(_EGL_DEBUG, "bad width or height (%dx%d)",
  80.             attrs.Width, attrs.Height);
  81.       return NULL;
  82.    }
  83.  
  84.    switch (attrs.DRMBufferFormatMESA) {
  85.    case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
  86.       format = PIPE_FORMAT_B8G8R8A8_UNORM;
  87.       break;
  88.    default:
  89.       _eglLog(_EGL_DEBUG, "bad image format value 0x%04x",
  90.             attrs.DRMBufferFormatMESA);
  91.       return NULL;
  92.       break;
  93.    }
  94.  
  95.    valid_use = EGL_DRM_BUFFER_USE_SCANOUT_MESA |
  96.                EGL_DRM_BUFFER_USE_SHARE_MESA |
  97.                EGL_DRM_BUFFER_USE_CURSOR_MESA;
  98.    if (attrs.DRMBufferUseMESA & ~valid_use) {
  99.       _eglLog(_EGL_DEBUG, "bad image use bit 0x%04x",
  100.             attrs.DRMBufferUseMESA);
  101.       return NULL;
  102.    }
  103.  
  104.    memset(&templ, 0, sizeof(templ));
  105.    templ.target = PIPE_TEXTURE_2D;
  106.    templ.format = format;
  107.    templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
  108.    templ.width0 = attrs.Width;
  109.    templ.height0 = attrs.Height;
  110.    templ.depth0 = 1;
  111.    templ.array_size = 1;
  112.  
  113.    /*
  114.     * XXX fix apps (e.g. wayland) and pipe drivers (e.g. i915) and remove the
  115.     * size check
  116.     */
  117.    if ((attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA) &&
  118.        attrs.Width >= 640 && attrs.Height >= 480)
  119.       templ.bind |= PIPE_BIND_SCANOUT;
  120.    if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA)
  121.       templ.bind |= PIPE_BIND_SHARED;
  122.    if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA) {
  123.       if (attrs.Width != 64 || attrs.Height != 64)
  124.          return NULL;
  125.       templ.bind |= PIPE_BIND_CURSOR;
  126.    }
  127.  
  128.    return screen->resource_create(screen, &templ);
  129. }
  130.  
  131. static struct pipe_resource *
  132. egl_g3d_reference_drm_buffer(_EGLDisplay *dpy, EGLint name,
  133.                              _EGLImage *img, const EGLint *attribs)
  134. {
  135.    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
  136.    _EGLImageAttribs attrs;
  137.    EGLint format;
  138.    struct native_buffer nbuf;
  139.  
  140.    if (!dpy->Extensions.MESA_drm_image)
  141.       return NULL;
  142.  
  143.    if (_eglParseImageAttribList(&attrs, dpy, attribs) != EGL_SUCCESS)
  144.       return NULL;
  145.  
  146.    if (attrs.Width <= 0 || attrs.Height <= 0 ||
  147.        attrs.DRMBufferStrideMESA <= 0) {
  148.       _eglLog(_EGL_DEBUG, "bad width, height, or stride (%dx%dx%d)",
  149.             attrs.Width, attrs.Height, attrs.DRMBufferStrideMESA);
  150.       return NULL;
  151.    }
  152.  
  153.    switch (attrs.DRMBufferFormatMESA) {
  154.    case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA:
  155.       format = PIPE_FORMAT_B8G8R8A8_UNORM;
  156.       break;
  157.    default:
  158.       _eglLog(_EGL_DEBUG, "bad image format value 0x%04x",
  159.             attrs.DRMBufferFormatMESA);
  160.       return NULL;
  161.       break;
  162.    }
  163.  
  164.    memset(&nbuf, 0, sizeof(nbuf));
  165.    nbuf.type = NATIVE_BUFFER_DRM;
  166.    nbuf.u.drm.templ.target = PIPE_TEXTURE_2D;
  167.    nbuf.u.drm.templ.format = format;
  168.    nbuf.u.drm.templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
  169.    nbuf.u.drm.templ.width0 = attrs.Width;
  170.    nbuf.u.drm.templ.height0 = attrs.Height;
  171.    nbuf.u.drm.templ.depth0 = 1;
  172.    nbuf.u.drm.templ.array_size = 1;
  173.  
  174.    nbuf.u.drm.name = name;
  175.    nbuf.u.drm.stride =
  176.       attrs.DRMBufferStrideMESA * util_format_get_blocksize(format);
  177.  
  178.    return gdpy->native->buffer->import_buffer(gdpy->native, &nbuf);
  179. }
  180.  
  181. #endif /* EGL_MESA_drm_image */
  182.  
  183. #ifdef EGL_WL_bind_wayland_display
  184.  
  185. static struct pipe_resource *
  186. egl_g3d_reference_wl_buffer(_EGLDisplay *dpy, struct wl_buffer *buffer,
  187.                             _EGLImage *img, const EGLint *attribs)
  188. {
  189.    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
  190.    struct pipe_resource *resource = NULL, *tmp = NULL;
  191.  
  192.    if (!gdpy->native->wayland_bufmgr)
  193.       return NULL;
  194.  
  195.    tmp = gdpy->native->wayland_bufmgr->buffer_get_resource(gdpy->native, buffer);
  196.  
  197.    pipe_resource_reference(&resource, tmp);
  198.  
  199.    return resource;
  200. }
  201.  
  202. #endif /* EGL_WL_bind_wayland_display */
  203.  
  204. #ifdef EGL_ANDROID_image_native_buffer
  205.  
  206. static struct pipe_resource *
  207. egl_g3d_reference_android_native_buffer(_EGLDisplay *dpy,
  208.                                         struct ANativeWindowBuffer *buf)
  209. {
  210.    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
  211.    struct native_buffer nbuf;
  212.  
  213.    memset(&nbuf, 0, sizeof(nbuf));
  214.    nbuf.type = NATIVE_BUFFER_ANDROID;
  215.    nbuf.u.android = buf;
  216.    
  217.    return gdpy->native->buffer->import_buffer(gdpy->native, &nbuf);
  218. }
  219.  
  220. #endif /* EGL_ANDROID_image_native_buffer */
  221.  
  222. _EGLImage *
  223. egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx,
  224.                      EGLenum target, EGLClientBuffer buffer,
  225.                      const EGLint *attribs)
  226. {
  227.    struct pipe_resource *ptex;
  228.    struct egl_g3d_image *gimg;
  229.    unsigned level = 0, layer = 0;
  230.  
  231.    gimg = CALLOC_STRUCT(egl_g3d_image);
  232.    if (!gimg) {
  233.       _eglError(EGL_BAD_ALLOC, "eglCreateEGLImageKHR");
  234.       return NULL;
  235.    }
  236.  
  237.    if (!_eglInitImage(&gimg->base, dpy)) {
  238.       FREE(gimg);
  239.       return NULL;
  240.    }
  241.  
  242.    switch (target) {
  243.    case EGL_NATIVE_PIXMAP_KHR:
  244.       ptex = egl_g3d_reference_native_pixmap(dpy,
  245.             (EGLNativePixmapType) buffer);
  246.       break;
  247. #ifdef EGL_MESA_drm_image
  248.    case EGL_DRM_BUFFER_MESA:
  249.       ptex = egl_g3d_reference_drm_buffer(dpy,
  250.             (EGLint) pointer_to_intptr(buffer), &gimg->base, attribs);
  251.       break;
  252. #endif
  253. #ifdef EGL_WL_bind_wayland_display
  254.    case EGL_WAYLAND_BUFFER_WL:
  255.       ptex = egl_g3d_reference_wl_buffer(dpy,
  256.             (struct wl_buffer *) buffer, &gimg->base, attribs);
  257.       break;
  258. #endif
  259. #ifdef EGL_ANDROID_image_native_buffer
  260.    case EGL_NATIVE_BUFFER_ANDROID:
  261.       ptex = egl_g3d_reference_android_native_buffer(dpy,
  262.             (struct ANativeWindowBuffer *) buffer);
  263.       break;
  264. #endif
  265.    default:
  266.       ptex = NULL;
  267.       break;
  268.    }
  269.  
  270.    if (!ptex) {
  271.       FREE(gimg);
  272.       return NULL;
  273.    }
  274.  
  275.    if (level > ptex->last_level) {
  276.       _eglError(EGL_BAD_MATCH, "eglCreateEGLImageKHR");
  277.       pipe_resource_reference(&gimg->texture, NULL);
  278.       FREE(gimg);
  279.       return NULL;
  280.    }
  281.    if (layer >= (u_minify(ptex->depth0, level) + ptex->array_size - 1)) {
  282.       _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
  283.       pipe_resource_reference(&gimg->texture, NULL);
  284.       FREE(gimg);
  285.       return NULL;
  286.    }
  287.  
  288.    /* transfer the ownership to the image */
  289.    gimg->texture = ptex;
  290.    gimg->level = level;
  291.    gimg->layer = layer;
  292.  
  293.    return &gimg->base;
  294. }
  295.  
  296. EGLBoolean
  297. egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img)
  298. {
  299.    struct egl_g3d_image *gimg = egl_g3d_image(img);
  300.  
  301.    pipe_resource_reference(&gimg->texture, NULL);
  302.    FREE(gimg);
  303.  
  304.    return EGL_TRUE;
  305. }
  306.  
  307. _EGLImage *
  308. egl_g3d_create_drm_image(_EGLDriver *drv, _EGLDisplay *dpy,
  309.                          const EGLint *attribs)
  310. {
  311.    struct egl_g3d_image *gimg;
  312.    struct pipe_resource *ptex;
  313.  
  314.    gimg = CALLOC_STRUCT(egl_g3d_image);
  315.    if (!gimg) {
  316.       _eglError(EGL_BAD_ALLOC, "eglCreateDRMImageKHR");
  317.       return NULL;
  318.    }
  319.  
  320.    if (!_eglInitImage(&gimg->base, dpy)) {
  321.       FREE(gimg);
  322.       return NULL;
  323.    }
  324.  
  325. #ifdef EGL_MESA_drm_image
  326.    ptex = egl_g3d_create_drm_buffer(dpy, &gimg->base, attribs);
  327. #else
  328.    ptex = NULL;
  329. #endif
  330.    if (!ptex) {
  331.       FREE(gimg);
  332.       return NULL;
  333.    }
  334.  
  335.    /* transfer the ownership to the image */
  336.    gimg->texture = ptex;
  337.    gimg->level = 0;
  338.    gimg->layer = 0;
  339.  
  340.    return &gimg->base;
  341. }
  342.  
  343. EGLBoolean
  344. egl_g3d_export_drm_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img,
  345.                          EGLint *name, EGLint *handle, EGLint *stride)
  346. {
  347.    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
  348.    struct egl_g3d_image *gimg = egl_g3d_image(img);
  349.    struct native_buffer nbuf;
  350.  
  351.    if (!dpy->Extensions.MESA_drm_image)
  352.       return EGL_FALSE;
  353.  
  354.    memset(&nbuf, 0, sizeof(nbuf));
  355.    nbuf.type = NATIVE_BUFFER_DRM;
  356.    if (name)
  357.       nbuf.u.drm.templ.bind |= PIPE_BIND_SHARED;
  358.  
  359.    if (!gdpy->native->buffer->export_buffer(gdpy->native,
  360.                                             gimg->texture, &nbuf))
  361.       return EGL_FALSE;
  362.  
  363.    if (name)
  364.       *name = nbuf.u.drm.name;
  365.    if (handle)
  366.       *handle = nbuf.u.drm.handle;
  367.    if (stride)
  368.       *stride = nbuf.u.drm.stride;
  369.  
  370.    return EGL_TRUE;
  371. }
  372.